使用awk命令

时间:2016-06-26 08:22:27

标签: bash unix awk

民间, 我一直在使用awk命令使用awk删除重复项。我面临的问题是因为每行末尾的CRLF。在awk中有没有办法可以从比较中丢弃CRLF?

我使用的命令:awk '!seen[$0]++'

记录

HelloworldCRLF
how are youCRLF
Helloworld

第一个和第三个记录是相同的,我希望它被删除。我猜因为最后一行没有CRLF,所以它保留在输出中。我尝试在记录的末尾添加CRLF以确保awk命令将其删除,但确实如此,但有时最后一条记录确实有一个CRLF,我最终得到一个额外的空行(因为我添加了CRLF)。有没有办法解决这种情况?

顺便说一下,该文件是在windows中生成的。

3 个答案:

答案 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。