Ed *_*ton 10 unix awk dos2unix sed
这个问题的目的是提供一个答案,每天的问题,其答案是"你中有DOS行结束",所以我们可以简单地关闭他们,因为这一个的副本,而无需重复同样的答案,令人生厌.
注意:这不是任何现有问题的副本.本问答的目的不仅仅是提供"运行此工具"的答案,而且还要解释这个问题,以便我们可以在这里指出任何有相关问题的人,他们会找到一个明确的解释,为什么他们在这里也被指出作为运行的工具,解决他们的问题.我花了几个小时阅读所有现有的问答,他们都缺乏对问题的解释,可用于解决问题的替代工具,和/或可能的解决方案的优缺点/警告.他们中的一些人已经接受了一些非常危险且永远不应该使用的答案.
现在回到将导致推荐的典型问题:
我有一个包含1行的文件:
what isgoingon
Run Code Online (Sandbox Code Playgroud)
当我使用这个awk脚本打印它来反转字段的顺序时:
awk '{print $2, $1}' file
Run Code Online (Sandbox Code Playgroud)
而不是看到我期望的输出:
isgoingon what
Run Code Online (Sandbox Code Playgroud)
我得到的行应该在行的末尾出现在行的开头,覆盖行开头的一些文本:
whatngon
Run Code Online (Sandbox Code Playgroud)
或者我将输出拆分为2行:
isgoingon
what
Run Code Online (Sandbox Code Playgroud)
问题是什么,我该如何解决?
Ed *_*ton 15
问题是您的输入文件使用的是DOS行结尾CRLF而不是UNIX行结尾,LF而您正在运行UNIX工具,因此CR仍然是UNIX工具操作的数据的一部分.CR通常由表示\r,并且可以被看作是一个控制-M( ^M)时运行cat -vE上的文件,而LF是\n,并显示为$与cat -vE.
所以你的输入文件不仅仅是:
what isgoingon
Run Code Online (Sandbox Code Playgroud)
它实际上是:
what isgoingon\r\n
Run Code Online (Sandbox Code Playgroud)
你可以看到cat -v:
$ cat -vE file
what isgoingon^M$
Run Code Online (Sandbox Code Playgroud)
并且od -c:
$ od -c file
0000000 w h a t i s g o i n g o n \r \n
0000020
Run Code Online (Sandbox Code Playgroud)
所以当你在文件上运行像awk这样的UNIX工具(它被视为\n行结尾)时\n,读取该行的行为就会消耗掉,但这会将2个字段保留为:
<what> <isgoingon\r>
Run Code Online (Sandbox Code Playgroud)
请注意\r第二个字段的末尾.\r表示Carriage Return字面上是将光标返回到行首的指令,所以当你这样做时:
print $2, $1
Run Code Online (Sandbox Code Playgroud)
awk将打印isgoingon然后将光标返回到打印前的行的开头,what这就是为什么what看起来会覆盖开头的原因isgoingon.
要解决此问题,请执行以下任一操作:
dos2unix file
sed 's/\r$//' file
awk '{sub(/\r$/,"")}1' file
perl -pe 's/\r$//' file
Run Code Online (Sandbox Code Playgroud)
显然dos2unix是又名frodos一些UNIX变种(如Ubuntu的).
如果您决定tr -d '\r'按照通常的建议使用,请小心,因为这将删除文件中的所有内容 \r,而不仅仅是每行末尾的内容.
请注意,GNU awk将允许您通过简单设置来解析具有DOS行结尾的文件RS:
gawk -v RS='\r\n' '...' file
Run Code Online (Sandbox Code Playgroud)
但是其他awk不允许这样做,因为POSIX只需要awks来支持单个字符RS,而大多数其他awk将悄然截断RS='\r\n'为RS='\r'.你可能需要添加-v BINMODE=3for gawk来查看\rs,因为底层的C原语会在某些平台上剥离它们,例如cygwin.
需要注意的一点是,像Excel这样的Windows工具创建的CSV将CRLF用作行结尾,但可以LF嵌入到CSV的特定字段中,例如:
"field1","field2.1
field2.2","field3"
Run Code Online (Sandbox Code Playgroud)
是真的:
"field1","field2.1\nfield2.2","field3"\r\n
Run Code Online (Sandbox Code Playgroud)
因此,如果您只是将\r\ns 转换为\ns,那么您就不能再将换行中的换行符作为行结尾,因此如果您想这样做,我建议首先将所有场内换行符转换为其他内容,例如,这将转换为所有内部-field LFsto tabs并将所有行结尾转换CRLF为LFs:
gawk -v RS='\r\n' '{gsub(/\n/,"\t")}1' file
Run Code Online (Sandbox Code Playgroud)
在没有GNU awk的情况下做类似的事情只是作为一个练习,但与其他awks一样,它涉及组合CR在阅读时不会结束的行.
| 归档时间: |
|
| 查看次数: |
496 次 |
| 最近记录: |