【问题标题】:awk counting delimiter didnt go as expectedawk 计数分隔符没有按预期进行
【发布时间】:2021-01-27 12:25:28
【问题描述】:

我正在从我的客户数据中计算分隔符的数量,即“|@~”,实际上我必须这样做,因为有时我收到的分隔符更少或更多。我曾经使用这种语法来查找每行的分隔符数量:

awk -F "|@~" '{print NF-1}' myDATA

它通常工作,但不知何故,今天它只返回 2 个计数,同时我期望 6 个。在我手动检查数据后,我可以在那里看到 6 个分隔符,之后我尝试手动复制该行并将其粘贴到记事本++,令人惊讶的是,并非所有行都被复制,只有一些行,而且令人惊讶的是它只包含 2 个分隔符,正如脚本给我的那样。是什么原因造成的?

我看到并想复制的内容:0123|@~123123|@~21321303|@~00000009213123|@~ 002133123123.|@~ 000000000.|@~CITY

粘贴结果:0123|@~123123|@~21321303

缺少粘贴:|@~00000009213123|@~ 002133123123.|@~ 000000000.|@~CITY

似乎在第三个分隔符和第三个字段的最后一个字符之间有一些东西,因为我必须将它拆分复制 2 次到这个站点,这对于只返回 2 个 |@~ 分隔符的 awk 结果是有意义的,但是当然是 6 而不是 2。

【问题讨论】:

  • 您的code says 6。您一定没有复制您所拥有的确切文本。
  • 是的,它返回 6,但我说过我试图拆分复制这一行,以实现这一点(复制到这个站点),实际上它返回的原始文本不是 2 6 使用 awk,如果我尝试使用 CTRL+A > CTRL+C > CTRL+V 进行复制,它只会复制 PASTE RESULT。是 awk 不够强大,还是因为它检测到一些人眼看不到的字符,以某种方式返回 2,而不是 6,也许第三个字段的下一个字符(就在第三个分隔符之前)是删除其余行的命令?
  • 你能发布一个有问题的行的十六进制转储吗?文本可能包含控制字符。使用hexdump -c 轻松查看。
  • 您将FS 设置为-F="|@~"。请注意,如果FS 的长度超过一个字符,则会将其视为正则表达式。管道 (|) 在这里有特殊的含义。所以最好使用-F=\\|@~。由于gory escape details,您需要在此处双重转义|
  • @Socowi 不知何故我试图在网上找到十六进制编辑器,他说“你的记录得到 00h,它被 Windows 剪贴板解释为文本终止。这是否意味着我不能用 awk 解决这个问题?因为 awk 的工作方式与 Windows 剪贴板相同,后者在第三个分隔符旁边的第三个字段之后终止记录?

标签: bash unix awk


【解决方案1】:

正如您的 hexdump 透露的那样,您的文本文件中有空字节。

GNU Awk 4.1.4 和 5.1.0 似乎威胁到这些文件的结尾。示例:

$ awk '{print NF}' <<< $'a b c\nx y'
3
2
$ awk '{print NF}' <<< $'a\0 b c\nx y'
1

man awk 我还没有找到改变这种行为的方法。但是,您可能不希望文件中的空字节以开头。因此,您可以在应用awk 之前删除它们。要从文件中删除所有空字节,请使用以下命令:

tr -d \\0 < /path/to/broken/input/file > /path/to/fixed/output/file

【讨论】:

  • 许多 awk 实现使用已知存在空字节问题的 c 字符串。这很可能是相关的。我确实相信 GNU awk 对待字符串的方式不同。尽管如此,我在 4.2.x 甚至 4.0.x 中都看不到这个问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多