我不确定如何表达这个问题,因为大多数答案都是关于\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
通过包括GNUawk
和mawk
busybox在内的一些实现(这 3 个实现在基于 Linux 的系统上常见,我相信awk
Cygwin 默认是 GNU ),输入记录分隔符可以是正则表达式(而不是 POSIX 中的单个字符) 。awk
RS
在这些中,你可以这样做:
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(仅当记录分隔符不是换行符时相关)。
busybox
awk 包括所有 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
访问最后一列值。