【问题标题】:awk's record ranges: last field of the line is ignored?awk 的记录范围:该行的最后一个字段被忽略?
【发布时间】:2014-10-20 22:38:17
【问题描述】:

如果我有一个文件:

0
on
0
off
0
0
...

命令:

awk '$1 == "on", $1 == "off"' < file

什么都不返回。 奇怪的是,如果我将输入文件更改为:

0
on ;
0
off ;
0
0

返回值符合预期:

on ;
0
off ;

这里发生了什么?如果我的字段是最后一行,awk 似乎不喜欢它。 我尝试将$1 更改为$0,并将$0 == "on" 更改为$0 == "on\n",但没有成功。

有没有办法处理 awk 的记录范围是记录的最后一个字段?

参考:This page of the awk manual

【问题讨论】:

  • 哦,你的例子很难理解。
  • @AvinashRaj 阅读链接的网页后是否还不清楚?很短
  • 是的,它正确地返回了上述预期的输出。你想达到什么目的?
  • @Mary 使用cat -v file 检查不可打印的字符。还可以尝试在文件上运行dos2unix 并再次尝试使用awk。回车很可能被视为字符串的一部分,如果我的假设是正确的,awk '$1~"on", $1~"off"' 应该可以工作。
  • 如果没有dos2unix也可以使用sed -ie "s/\r//" file达到同样的效果。

标签: awk


【解决方案1】:

当你这样做时:

awk '...' < file

您正在通过标准输入流将文件传递给 awk。这和做的不一样

awk '...' file

将文件名传递给 awk 以使其打开。通常,这两种方法是等价的。但是,由于行尾不同,Windows 上会出现问题。

这个例子演示了这个问题:

$ awk '{for(i=1; i<=NF; ++i)print NR, i, "|"$i"|"}'  < file.txt
| 1 |0
| 1 |on
| 1 |0
| 1 |off
| 1 |0
6 1 |0|

将输出与此进行比较:

$ awk '{for(i=1; i<=NF; ++i)print NR, i, "|"$i"|"}' file.txt
1 1 |0|
2 1 |on|
3 1 |0|
4 1 |off|
5 1 |0|
6 1 |0|

第二个测试的输出是预期的。问题是回车 \r 在第一种情况下被解释为记录的一部分。

在 GNU awk 上,可以指定多字符记录分隔符,它允许您通过标准输入传递文件的内容:

$ awk '{for(i=1; i<=NF; ++i)print NR, i, "|"$i"|"}' RS='\r\n' < file.txt
1 1 |0|
2 1 |on|
3 1 |0|
4 1 |off|
5 1 |0|
6 1 |0|

【讨论】:

    【解决方案2】:

    您的输入文件中有 control-M,请在运行命令之前使用 dos2unix 或类似工具将其删除。

    另外 - 使用范围表达式从来都没有用,因为它们会使琐碎的事情稍微简单一些,但任何稍微复杂的事情(例如不打印开始和/或结束行)都会导致您编写重复的代码或做一个完整的重新-写。只需使用一个标志:

    awk '$1 == "on"{f=1} f; $1 == "off"{f=0}' file
    

    【讨论】:

      【解决方案3】:

      你可以试试下面的 awk 命令,

      $ awk '$1 == "on", $1 == "off"' file
      on
      0
      off
      

      awk -v RS="[\n\r]+" '$1 == "on", $1 == "off"' file
      

      输入文件中可能存在回车\r。所以将记录分隔符设置为[\n\r]+。此正则表达式会将一个或多个换行符或回车符作为值分配给记录分隔符变量。

      【讨论】:

      • 以美元符号开头?
      • @TomFenech 我认为他们遗漏了&lt;,但无论如何它都应该可以工作
      • 我认为这会有所帮助。 awk -v RS="[\n\r]+" '$1 == "on", $1 == "off"' file
      • @AvinashRaj:你赢了!那个怎么样?没看懂
      • 是的,这确实解决了我的 Windows 系统上使用 git bash 的问题(如果文件被重定向,我没有得到输出)。 @Mary,您不应该使用 &lt; 将文件重定向到 awk。我不认为这会导致问题,但显然确实会。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      • 2018-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多