【问题标题】:Using record separators in awk在 awk 中使用记录分隔符
【发布时间】:2012-10-25 23:22:34
【问题描述】:

我有

$ cat awktestf 
a++
b++
c++

我在做,我得到了

cat  awktestf | awk 'BEGIN { RS="++" ; OFS="@"; ORS="()" } { print $0 } END {print "I am done" }'
a()
b()
c()
()I am done()abc@abc:~$ 

我的问题是为什么我最后会得到一个额外的 ()?

即使这样也行不通:

$ echo 'a++
> b++
> c++' | awk 'BEGIN { RS="++" ; OFS="@"; ORS="()" } { print $0 } END {print "I am done" }'
a()
b()
c()
()I am done()abc@abc:~$ 

【问题讨论】:

  • 请注意 a) 这些是记录分隔符,而不是字段分隔符,2) 使用多字符 RS 使您的脚本特定于 gawk,3) 您不需要使用 cat 打开文件,awk 可以自己完成,并且 4)“print $0”是默认操作,因此您可以只说“{print}”,甚至是常见的惯用“1”。

标签: bash shell scripting awk


【解决方案1】:

ORS 附加到每个输出记录的末尾。因此,您的“我完成了”以 () 结尾。


第一次误解了这个问题。

这个

a++
b++
c++

翻译成

a++\nb++\nc++\n

使用RS拆分成记录后,得到这些记录

  1. 一个
  2. \nb
  3. \nc
  4. \n

当你打印它们时,每条记录都以ORS() 结束,所以

a()\nb()\nc()\n()

你添加了“我完成了”

a()\nb()\nc()\n()I am done()

因此显示为

a()
b()
c()
()I am done()

(由于最后一行不以换行符结尾,您的提示显示在同一行)

【讨论】:

  • 我不是在谈论那个()。我说的是“我完成了”开头的()
  • @abc:实际上有。 echo 默认在末尾添加一个换行符。这就是为什么当您运行echo "Something" 时,您的提示会出现在下一行。 echo -n 用于抑制这种行为(如果版本 echo 支持选项)。
  • +1 不错的答案。换行符可以用RS="++\n" 处理,但是你需要在 ORS 中换行符:ORS="()\n"
【解决方案2】:

您的文件末尾可能有一个空行。

由于OFS 设置为(),它会在打印到输出的每一行之后打印。只需从输入文件中删除空行即可。

旁注:您不必cat 文件然后通过管道传输到awk。只需使用awk:

awk ' .... ' file

【讨论】:

  • 我的输入文件中没有空行。我在上面添加了另一个示例。
  • @abc OFS 是原因。当您打印I am done 时,它的末尾有一个\n,它被OFS 替换,正如您告诉它的那样。
  • @KingsIndian: ITYM ORS 不是 OFS,并且从来没有要替换的 \n,ORS 只是打印在记录的末尾。
  • @EdMorton 感谢您的澄清。尽管我知道 ORS 是在每一行之后打印它的原因,但我不知何故没有正确解释它:)
猜你喜欢
  • 2014-01-07
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多