47

这是输入(样本):

name1@gmail.com|com.emailclient.account
name2@msn.com|com.socialsite.auth.account

我正在努力实现这一目标:

Emailclient name1@gmail.com
Socialsite name2@msn.com

如果我像这样使用 AWK:

cat foo | awk 'BEGIN{FS="|"} {print $2 " " $1}'

它通过在字段 2 的顶部覆盖字段 1 来弄乱输出。

任何提示/建议?谢谢你。

4

4 回答 4

83

几个一般提示(除了 DOS 行尾问题)

cat用于连接文件,它不是唯一可以读取文件的工具!如果命令不读取文件,则使用重定向,如command < file.

您可以使用选项设置字段分隔符,-F而不是:

cat foo | awk 'BEGIN{FS="|"} {print $2 " " $1}' 

尝试:

awk -F'|' '{print $2" "$1}' foo 

这将输出:

com.emailclient.account name1@gmail.com
com.socialsite.auth.accoun name2@msn.com

要获得所需的输出,您可以做很多事情。我可能split()是第二个领域:

awk -F'|' '{split($2,a,".");print a[2]" "$1}' file
emailclient name1@gmail.com
socialsite name2@msn.com

最后将第一个字符转换为大写有点麻烦,awk因为您没有一个很好的内置ucfirst()函数:

awk -F'|' '{split($2,a,".");print toupper(substr(a[2],1,1)) substr(a[2],2),$1}' file
Emailclient name1@gmail.com
Socialsite name2@msn.com

如果您想要更简洁的东西(尽管您放弃了子流程),您可以这样做:

awk -F'|' '{split($2,a,".");print a[2]" "$1}' file | sed 's/^./\U&/'
Emailclient name1@gmail.com
Socialsite name2@msn.com
于 2013-03-24T12:44:27.433 回答
3

使用点或管道作为字段分隔符:

awk -v FS='[.|]' '{
    printf "%s%s %s.%s\n", toupper(substr($4,1,1)), substr($4,2), $1, $2
}' << END
name1@gmail.com|com.emailclient.account
name2@msn.com|com.socialsite.auth.account
END

给出:

Emailclient name1@gmail.com
Socialsite name2@msn.com
于 2013-03-24T19:45:13.543 回答
2

awk 没问题。我猜该文件来自 Windows 系统,并且在行尾有一个 CR (^m ascii 0x0d)。

这将导致光标转到 $2 之后的行首。

使用 dos2unix 或 vi:se ff=unix来摆脱 CR。

于 2013-03-24T11:20:35.113 回答
2

也许您的文件包含 CRLF 终止符。每行后跟 \r\n。

awk承认$2其实$2\r。手段转到行的\r开头。

{print $2\r$1}$2先打印,然后返回头部,然后打印$1。所以字段 2 被字段 1 覆盖。

于 2017-06-27T16:51:46.013 回答