awk 似乎对 $1 是什么感到困惑

Iai*_*ain 9 awk

我使用 awk 来解析日志;我从未见过这样的事情:我有六个包含多行的文件;我想要包含“100”的那些,并选择要打印的列

me:~/tmp> grep 100 *.dl.tst
Run Code Online (Sandbox Code Playgroud)

输出我期望的:

100  139M  100  139M    0     0  6376k      0  0:00:22  0:00:22 --:--:-- 6539k
100  139M  100  139M    0     0  6677k      0  0:00:21  0:00:21 --:--:-- 6579k
100  139M  100  139M    0     0  6022k      0  0:00:23  0:00:23 --:--:-- 6093k
100  139M  100  139M    0     0  13.9M      0  0:00:10  0:00:10 --:--:-- 14.3M
100  139M  100  139M    0     0  14.3M      0  0:00:09  0:00:09 --:--:-- 14.7M
100  139M  100  139M    0     0  13.2M      0  0:00:10  0:00:10 --:--:-- 13.3M
Run Code Online (Sandbox Code Playgroud)

就像:

me:~/tmp> grep 100 *.dl.tst|awk '{print$0}'
100  139M  100  139M    0     0  6376k      0  0:00:22  0:00:22 --:--:-- 6539k
100  139M  100  139M    0     0  6677k      0  0:00:21  0:00:21 --:--:-- 6579k
100  139M  100  139M    0     0  6022k      0  0:00:23  0:00:23 --:--:-- 6093k
100  139M  100  139M    0     0  13.9M      0  0:00:10  0:00:10 --:--:-- 14.3M
100  139M  100  139M    0     0  14.3M      0  0:00:09  0:00:09 --:--:-- 14.7M
100  139M  100  139M    0     0  13.2M      0  0:00:10  0:00:10 --:--:-- 13.3M
Run Code Online (Sandbox Code Playgroud)

那么为什么会$1变成文件名:

me:~/tmp> grep 100 *.dl.tst|awk '{print$1}'
shpr002.20201124_141036.dl.tst:
shpr003.20201124_141036.dl.tst:
shpr004.20201124_141036.dl.tst:
hipr002.20201124_141036.dl.tst:
hipr003.20201124_141036.dl.tst:
hipr004.20201124_141036.dl.tst:
Run Code Online (Sandbox Code Playgroud)

并且$2

me:~/tmp> grep 100 *.dl.tst|awk '{print$2}'
0
0
0
0
0
0
Run Code Online (Sandbox Code Playgroud)

我注销并重新登录,以防我的 shell (bash) 搞砸了;没有变化......我做错了什么?

输出grep 100 *.dl.tst | awk '{print$1}' | head -n1 | od -c (一些字母字符已被替换x;上面的列表已被编辑/混淆)

0000000   x  s   h   p   r   0   0   2   x   x   x  .   x   x   x   .
0000020   x   x   x   x   .   c   o   m   .   2   0   2   0   -   1   1
0000040   -   2   4   _   1   4   1   0   3   6   .   d   l   .   t   s
0000060   t   :  \r  \n
0000064
Run Code Online (Sandbox Code Playgroud)

Ste*_*itt 16

这些文件包含curl下载文件的输出,并curl在下载过程中通过输出回车(通常表示为\r,用于在许多上下文中产生它的转义)更新其进度信息,这会导致光标返回到线。

当您运行 时grep 100 *.dl.tst,输出的每一行都以文件名开头,但随后是多个更新,这些更新将光标返回到行的开头,因此您看不到文件名——它被后续输出覆盖。更详细地说,输出看起来像

shpr002.20201124_141036.dl.tst:
Run Code Online (Sandbox Code Playgroud)

后面跟着一个回车,后面跟着第一个进度输出curl

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
Run Code Online (Sandbox Code Playgroud)

然后是回车等,直到百分比达到100。因为所有这些只是由回车分隔,而不是换行符,所以它算作一行,并grep与整个行匹配。

同样的效果解释了 的输出grep 100 *.dl.tst|awk '{print$0}'

当您要求 AWK 输出时$1,它输出第一个字段,现在您可以看到它:它包含文件名、冒号、回车符,仅此而已 -curl输出的开头然后以空格开头(到为百分比计数留出空间),这是一个字段分隔符。当您要求它 output 时$2,它会输出第二个字段,即第一个百分比计数0

shpr002.20201124_141036.dl.tst:\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0

<--          Field 1          -->  !     !    !     !  ...
                                   $2    $3   $4    $5 ...
Run Code Online (Sandbox Code Playgroud)