awk 的第一个语句中是否必须有一个变量?

awk 的第一个语句中是否必须有一个变量?

今天我在 awk 上遇到了一些困难。如果我尝试这样做:

df|awk '{print $2; $some=$2; print $some}'

它按预期工作,我得到磁盘大小两次,但如果我这样做:

df|awk '{$some=$2; print $some}'

我只是得到空行。为什么会发生这种情况?我的理解可能有问题,但为什么必须使用一个字段才能使后续字段正常工作?我也尝试这样做:

df|awk '{print "hello"; $some=$2; print $some}'

我得到了一些“你好”,每个都用换行符分隔。 $some=$2 丢失在哪里?

我的df命令输出:

Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/sda5       38448788 32098732   4396932  88% /
udev             1914564        4   1914560   1% /dev
tmpfs             768744      984    767760   1% /run

答案1

您不应$在 前面使用 - 符号some。发生的情况是,您的第一个命令 $2被打印,然后$some=$2转换为$0=$2sincesome是unialized(在某些awk实现中从tosome转换,而不是全部(然后您收到错误消息)),因此您将记录()替换为.然后你打印,这意味着 So it is equal to""0$0$2$some$0

df|awk '{print $2; $0=$2; print $0}'

df|awk '{$0=$2; print $0}'

你可能想做的是:

df|awk '{print $2; some=$2; print some}'

答案2

我得到了预期的结果。第一个命令将每个项目打印两次。第二个命令将其打印一次。

这是相当不传统的——“some”默认值为零,因为它是未定义的。因此 $some 是 $0,它代表整行,所以基本上你在使用时用 $2 中找到的任何内容替换该行$some=$2

与此结果进行比较:

johan@computer:~$ df|awk '{$some=$2; print}'
1K-blocks
30827524
4041028
1621692
5120
4054228
102400
4054228
60555340
209548784

为什么你不会得到任何输出或不同的结果:我预计使用未初始化变量的行为可能是未定义的,至少在某些系统上是这样。

在 Solaris 上,我可以访问“标准”awk 以及安装在 /usr/xpg4/bin/awk 中的据称符合 POSIX 的版本。对于以下内容,这两者都会产生相同的结果

它们会产生不同的结果,具体取决于我是否在前面添加 print“hello”,以及是否用“print”(而不是 print $some)替换最后一个命令。

不过,它们都打印了一些东西,而不是空白 - 我还没有找到一个能够重现这种效果的版本。

所以我预计这是由于使用未初始化的变量而导致的某种未定义的行为 -您正在为一列分配一个值,该值可能远远超过可能的列范围的末尾在输入流中。 $some 指的是由“some”的值标识的列

你应该只使用“some”作为变量,例如

df | awk '{print "hello";some=$2; print some}'

答案3

我认为发生这种情况的原因是 Ubuntu 不使用标准的 GNU 植入,而是使用其他称为 mawk 的东西,它破坏了许多在标准 unix 下工作的代码。

请参考这个关联进行类似的讨论。

相关内容