为什么AWK会删除领先空间?

时间:2015-08-27 14:19:15

标签: awk

为什么以下示例中未打印前导空格?

$ echo " foo bar" | awk '{ $2 = "baz"; print $0 }'
foo baz

3 个答案:

答案 0 :(得分:4)

每当你“触摸”记录中的字段时(在这种情况下通过分配给第二个字段),awk会重新格式化整个记录。因此$1为“foo”,每个字段由输出字段分隔符OFS分隔,默认情况下为单个空格。

为了保持线条完整,您可以将代码更改为以下内容:

$ echo " foo bar" | awk '{ sub(/bar/, "baz"); print $0 }'
 baz bar

作为一个整体而不是单个字段在线上操作意味着不会重新格式化。

......虽然在那时,你也可以使用sed:

$ echo " foo bar" | sed 's/bar/baz/'
 baz bar

答案 1 :(得分:4)

无论何时修改记录的字段,awk都会重新编译记录,使用OFS的值分隔字段并从记录中删除前导和尾随空白。为了保持空白区域的完整性,您必须修改整个记录,而不是修改它的任何一个字段。

例如,用GNU awk做你想做的事情:

$ echo " foo bar" | awk '{ $0=gensub(/(^\s*\S+\s+).*/,"\\1baz",""); print $0 }'
 foo baz

不要认为只能做sub(/bar/,"baz"),因为当记录中出现“bar”而不是第二个字段时会失败:

$ echo " rhubarb bar" | awk '{ sub(/bar/, "baz"); print $0 }'
 rhubazb bar

$ echo " rhubarb bar" | awk '{ $0=gensub(/(^\s*\S+\s+).*/,"\\1baz",""); print $0 }'
 rhubarb baz

通常,要替换字段由默认FS分隔的记录的第N个字段,请执行以下操作:

$0=gensub(/((^\s*\S+\s+){N-1})\S+/,"\\1baz","")

并且对于在字符类中无法否定的FS值,这次使用GNU awk为第4个arg分割():

awk -F'<whatever>' '{split($0,f,FS,s); f[2]="baz"; r=s[0]; for (i=i;i<=NF;i++) r=r f[i] s[i]; $0=r; print $0}'

答案 2 :(得分:2)

awk在空格上分割线条。

对于该行,awk设置$1="foo"$2="bar"

当你没有修改关于某行的任何内容时,只需将输出行打印出来。

当您修改该行时(通过指定其中一个字段),awk重新组合字段以形成输出行(它使用OFS的值重新组合字段)。

所以awk会占用你的两个字段(现在$1="foo"$2="baz")并且(有效地)这样做:

printf "%s%s%s\n", $1, OFS, $2