2016-06-26 55 views
2

Folks, 我一直在使用awk命令删除使用awk的重复项。问题是我面对的是因为每行结尾都有CRLF。 awk中有没有一种方法可以从比较中放弃CRLF?使用awk命令删除带有CRLF的重复文件

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

记录

HelloworldCRLF 
how are youCRLF 
Helloworld 

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

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

+0

@WalterA会从整个文件中删除'\ r's,而不是每行的结尾,在任何情况下额外的'\ r's都不是OP问题,他的问题是缺少的新行(CRLF在他的情况下)在文件的末尾。 –

回答

2

您可以在CRLF序列添加到记录分隔符:

awk -v RS='\n|\r\n' '!seen[$0]++' file 
+1

只能在GNU awk或其他允许多字符RS的非POSIX awk中使用。你可以更简洁地写成'RS ='\ r?\ n''顺便说一句。这不是OP的问题,但是,他的问题是文件末尾缺失的换行符(在他的情况下是CRLF)。 –

3

在进行比较之前更换的\r任何实例。

awk '{gsub(/\r/,"")}; !seen[$0]++' 
+0

这将删除任何'\ r'中线。你应该真的使用'/ \ r $ /'。这不是OP的问题,但是,他的问题是文件末尾缺失的换行符(在他的情况下是CRLF)。 –

2

你的问题不在于视窗每LF前加入(CRS其他人一样,到目前为止似乎认为),它是你的文件在最后缺少一个换行符(其中Windows是CRLF组合)的文件。当针对没有终止换行符的文件运行UNIX命令时,所有投注都将关闭,因为在那时该文件不再是真正的“文本文件”。你能修改生成文件的任何工具来产生一个终止的换行符吗?如果没有,那么在运行awk或其他任何工具之前,请执行

printf '\r\n' >> file 

。那么你可以运行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来从剥离\r S中的GAWK脚本看到之前停止下级元,使用-v BINDMODE=3与GAWK。

关于评论中的问题,以下是为什么您不能在每个出现在您的dodorstep上的文件上运行dos2unix。想象此文件使用回车(控制-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是空的第1行,而字段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。

+0

文件末尾可能有新行,并且可能不存在。我看到添加它可以解决问题,我这样做了,但是当文件已经作为新行,然后下一个读取这个过程将它视为空记录。一旦它进入Unix系统,对所有文件执行dos2unix是否是一种很好的做法? – Garfield

+0

否,因为不是每个文件都使用回车换行符作为记录分隔符,它可能只是文件中数据的一部分。这一切都取决于在应用程序中换行('\ n')之前回车('\ r')**意味着什么。我在我的答案中添加了一个示例,以说明为什么不能盲目地在每个文件上运行'dos2unix'的原因。另外,dos2unix不会解决你的缺失新行问题 - 它只是在'\ n's之前剥去'\ r's,它不会在文件末尾添加缺失的新行。谷歌如何处理这一问题。 –

+0

挂上 - 为什么选择http://stackoverflow.com/a/38036695/1745001作为您接受的答案?答案试图解决的问题(dos行结束)与你的问题完全没有关系(在文件结尾处缺少换行符),如果这是你的问题,那将不是正确的解决方案。 –