awk CR LF处理是否打破了cygwin?

时间:2014-06-16 20:02:43

标签: linux bash awk

在Linux上,这按预期运行:

$ echo -e "line1\r\nline2"|awk -v RS="\r\n" '/^line/ {print "awk: "$0}'
awk: line1
awk: line2

但在windows下\ r \ n被删除(awk认为这一行):

视窗:

$ echo -e "line1\r\nline2"|awk -v RS="\r\n" '/^line/ {print "awk: "$0}'
awk: line1
line2

Windows GNU Awk 4.0.1 Linux GNU Awk 3.1.8

来自@EdMorton的编辑(对不起,如果这是一个不需要的补充,但我认为这可能有助于证明这个问题):

考虑这个RS设置和输入(在cygwin上):

$ awk 'BEGIN{printf "\"%s\"\n", RS}' | cat -v
"
"
$ echo -e "line1\r\nline2" | cat -v
line1^M
line2

这是带有gawk的Solaris:

$ echo -e "line1\r\nline2" | awk '1' | cat -v   
line1^M
line2

这是ggk的cygwin:

$ echo -e "line1\r\nline2" | awk '1' | cat -v
line1
line2

RS只是它的默认换行符所以控件-M在哪里进入cygwin?

2 个答案:

答案 0 :(得分:7)

我刚刚与Arnold Robbins(gawk的提供者)进行了核实,答案是它是由C库完成的并且为了阻止它发生你应该将awk BINMODE变量设置为3:

$ echo -e "line1\r\nline2" | awk '1' | cat -v
line1
line2

$ echo -e "line1\r\nline2" | awk -v BINMODE=3 '1' | cat -v
line1^M
line2

如果感兴趣,请参阅手册页以获取更多信息。

答案 1 :(得分:4)

在Cygwin下,问题似乎是awk 我尝试了一些不同的东西,似乎awk默默地在输入数据中用\r\n替换\n

如果我们只是要求awk重复未经修改的文字,它将"清理"马车返回时没有问:

$ echo -e "line1\r\nline2" | od -a
0000000   l   i   n   e   1  cr  nl   l   i   n   e   2  nl
0000015

$ echo -e "line1\r\nline2" | awk '{ print $0; }' | od -a
0000000   l   i   n   e   1  nl   l   i   n   e   2  nl
0000014
但是,它会使其他回车保持不变:

$ echo -e "Test\rTesting\r\nTester\rTested" | awk '{ print $0; }' | od -a
0000000   T   e   s   t  cr   T   e   s   t   i   n   g  nl   T   e   s
0000020   t   e   r  cr   T   e   s   t   e   d  nl
0000033

使用_的自定义记录分隔符,最后使回车保持原样:

$ echo -e "Testing\r_Tested" | awk -v RS="_" '{ print $0; }' | od -a
0000000   T   e   s   t   i   n   g  cr  nl   T   e   s   t   e   d  nl
0000020  nl
0000021

最有说服力的例子涉及在数据中使用\r\n,但不能作为记录分隔符:

$ echo -e "Testing\r\nTested_Hello_World" | awk -v RS="_" '{ print $0; }' | od -a
0000000   T   e   s   t   i   n   g  nl   T   e   s   t   e   d  nl   H
0000020   e   l   l   o  nl   W   o   r   l   d  nl  nl
0000034

awk在输入数据中盲目地将\r\n转换为\n,即使我们没有要求它。

这种替换似乎是在应用记录分离之前发生的,这解释了为什么RS="\r\n"永远不匹配任何东西。当awk正在寻找\r\n时,它已经在输入数据中用\n替换了它。