民间, 我一直在使用awk命令使用awk删除重复项。我面临的问题是因为每行末尾的CRLF。在awk中有没有办法可以从比较中丢弃CRLF?
我使用的命令:awk '!seen[$0]++'
记录
HelloworldCRLF
how are youCRLF
Helloworld
第一个和第三个记录是相同的,我希望它被删除。我猜因为最后一行没有CRLF,所以它保留在输出中。我尝试在记录的末尾添加CRLF以确保awk命令将其删除,但确实如此,但有时最后一条记录确实有一个CRLF,我最终得到一个额外的空行(因为我添加了CRLF)。有没有办法解决这种情况?
顺便说一下,该文件是在windows中生成的。
答案 0 :(得分:3)
在进行比较之前替换\r
的任何实例。
awk '{gsub(/\r/,"")}; !seen[$0]++'
答案 1 :(得分:2)
您可以将CRLF序列添加到记录分隔符:
awk -v RS='\n|\r\n' '!seen[$0]++' file
答案 2 :(得分:2)
你的问题不是Windows在每个LF之前添加了CR(正如其他人到目前为止所想的那样),而是你的文件在文件末尾缺少换行符(对于Windows是CRLF组合)。对没有终止换行符的文件运行UNIX命令时,所有的赌注都会关闭,因为此时它不再是真正的“文本文件”。你可以修改生成文件的任何工具来生成终止换行符吗?如果没有,那么
printf '\r\n' >> file
在运行awk或其他任何工具之前。然后,如果需要,您可以运行dos2unix
或任何其他建议来处理/删除\r
。例如:
$ cat -v file
Helloworld^M
how are you^M
Helloworld$
请注意$
,这是我在最后Helloworld
之后的提示,因为文件中缺少换行符。现在:
$ awk -v BINMODE=3 '!seen[$0]++' file | cat -v
Helloworld^M
how are you^M
Helloworld
$
$ printf '\r\n' >> file
$
$ awk -v BINMODE=3 '!seen[$0]++' file | cat -v
Helloworld^M
how are you^M
$
$ dos2unix file
dos2unix: converting file file to Unix format...
$
$ awk '!seen[$0]++' file | cat -v
Helloworld
how are you
$
我必须在上面的cygwin中使用-v BINDMODE=3
gawk来阻止较低级别的原语在gawk脚本看到它们之前剥离\r
。
在评论中提出问题,这就是为什么你不能只在你的dodorstep上显示的每个文件上运行dos2unix。想象一下这个文件使用回车符(control-Ms)作为字段分隔符:
$ printf 'a\rb\r\nd\r\rf\n' > file
$ cat -v file
a^Mb^M
d^M^Mf
$ awk -v BINMODE=3 -F'\r' '{for (i=1;i<=NF;i++) print NF, i, "<"$i">"; print "----"}' file
3 1 <a>
3 2 <b>
3 3 <>
----
3 1 <d>
3 2 <>
3 3 <f>
----
正如您所看到的,awk正确识别每行有3个字段,第3行的字段3为空,而第2行的字段2为空。现在让我们运行dos2unix并再试一次:
$ dos2unix file
dos2unix: converting file file to Unix format...
$ cat -v file
a^Mb
d^M^Mf
$ awk -v BINMODE=3 -F'\r' '{for (i=1;i<=NF;i++) print NF, i, "<"$i">"; print "----"}' file
2 1 <a>
2 2 <b>
----
3 1 <d>
3 2 <>
3 3 <f>
----
正如您所看到的,dos2unix
通过从第1行剥离空字段3来损坏文件,因为当它看到\r\n
时,它认为这是一个dos行结束,而不是FS后跟RS。