如何从 awk $NF 列中删除 CRLF

如何从 awk $NF 列中删除 CRLF

我不确定如何表达这个问题,因为大多数答案都是关于\r\n从文件中删除。

我有一个独特的问题,压缩文件是随机编号的,为了将它们与数据库记录正确关联,我需要列出文件内容并检查它们。

我正在使用这个解决方案 “在bash脚本中,如何逐行捕获stdout”

这是一个很好的开始。

有些内容的名称带有空格,我找到了这个解决方案: 如何打印第三列到最后一列?

我发现在尝试更新数据库记录时,该记录^M被插入管道的结果中awk,但仅限于NF列。

不确定如何解决这个特定的故障。我不知道在哪里^M插入,或者如何从最后一列中删除它。

我的代码

如果我剥离这条线就可以正常工作^M

filename="$(echo "$line" | awk '{if ($3 ~ /^M$/) {sub(/^M$/,"", $3)} printf $3; printf ""}')"

此行失败:

text="$(echo "$line" | awk '{for(i=6;i<NF+1;i++) {if ($i ~ /^M$/) {sub(/^M$/,"", $i)} } printf "%s ", $i; printf ""}')"

简化版本失败了:

text="$(echo "$line" | awk '{for(i=6;i<NF+1;i++) sub(/^M$/,"", $i) printf "%s ", $i; printf ""}')"

vim/中 使用Usingvi ^M创建没有任何效果。ctrl-V + <return key>\r\n

我正在使用cygwin,并且已经使用了很长一段时间,并且我*nix编写了其他运行良好的脚本。我发现由于某种原因,这个特定的运行awk正在添加^M到输出中。

我发现这个问题有类似的问题,但我vim从一开始就创建了我的脚本,所以没有涉及基于 Windows 的编辑器。

如果我将该 Windows 文件夹安装为 samba 共享并从 linux 运行脚本,它会生成不带 的输出^M,所以此时我想知道这是否是一个错误或其他问题。真的很奇怪。

更新 我在 sub() 中使用 REGEX 导致字符串返回空,所以我没有正确理解如何清除 CRLF。

NF+1 是我之前使用 i<=NF 尝试找出引入 CRLF 的剩余内容。

答案1

awk通过包括GNUawkmawkbusybox在内的一些实现(这 3 个实现在基于 Linux 的系统上常见,我相信awkCygwin 默认是 GNU ),输入记录分隔符可以是正则表达式(而不是 POSIX 中的单个字符) 。awkRS

在这些中,你可以这样做:

awk -v RS='\r\n' '{print $NF}' < your-file.msdos

处理这些文件,或者:

awk -v RS='\r?\n' '{print $NF}' < your-file.msdos-or-unix

能够使用\n定界符或\r\n分隔符处理这两个文件。

一些 MS-DOS 文件也倾向于最后一行不带分隔符,但awk也会在输出时修复该问题,因为它在打印时将输出记录分隔符(ORS保留\n在此处)附加到所有记录。

就默认字段分割而言awk,您还会发现实现之间存在差异。 POSIX 说它应该被分割成序列空白,删除前导和尾随。的概念空白的与区域设置相关,并且至少包括 SPC 和 TAB。您会发现许多awk实现仅将其限制为 SPC 和 TAB,而不管区域设置如何,许多实现还添加 NL(仅当记录分隔符不是换行符时相关)。

busyboxawk 包括所有 ASCII 空白,因此包括CR, FF, VT。所以在 busybox 中awk,默认情况下字段从不包含 CR。您可以使用 GNU 实现相同的行为,awk方法是将gawk -v 'FPAT=[^[:space:]]'其中字段定义为非空白序列。

还有一些注意事项:

  • 避免 shell 循环处理文本,尤其是在这里,因为您已经在使用awk这是处理文本的正确工具之一。
  • 不要用于echo任意数据
  • 第一个参数printf是格式,您不想在那里使用任意数据。printf "%s", $3如果您想$3在不附加的情况下打印,请使用ORS,而不是printf $3
  • printf ""是一个空操作。它没有任何作用。如果要打印换行符,请使用printf "\n"print ""(后者ORS默认打印 , 换行符)。

答案2

awk不识别^M字面意思,而是将其识别为 CRLF 模式\r\n,因此您sub()可以直接使用 CR 字符表示,如下所示。此外,您不必检查该字段是否包含字符并进行替换。如果未找到上述模式,则替换函数将不执行任何操作。因此,您只需要使用以下内容来替换最后一列的 CR。

awk '{ sub("\r", "", $NF); print $NF }' 

如果需要更换多个色谱柱,请切换$NF到所需的适当色谱柱。

如果您在循环中对直到文件末尾的所有列执行此操作,只需执行

awk '{ for(i=6; i<=NF ; i++) { sub("\r", "", $i); printf "%s ", $i; } }'

此外,文件只能有最大NF列,并且$NF是最后一列值。将循环更改为运行直到NF访问最后一列值。

相关内容