Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 为什么我的工具输出会覆盖自身,如何修复它?_Unix_Awk_Sed_Dos2unix - Fatal编程技术网

Unix 为什么我的工具输出会覆盖自身,如何修复它?

Unix 为什么我的工具输出会覆盖自身,如何修复它?,unix,awk,sed,dos2unix,Unix,Awk,Sed,Dos2unix,这个问题的目的是为回答“您有DOS行结尾”的日常问题提供答案,这样我们就可以简单地将它们作为本问题的副本关闭,而不必重复同样的答案 注意:这不是任何现有问题的重复。本问答的目的不仅仅是提供一个“运行此工具”的答案,而且是解释问题,这样我们就可以在这里向任何人提出相关问题,他们就会清楚地解释为什么在这里提出这些问题,以及运行此工具以解决他们的问题。我花了几个小时阅读了所有现有的问答,它们都缺乏对问题的解释、可用于解决问题的替代工具和/或可能解决方案的优缺点/注意事项。此外,他们中的一些人已经接受了

这个问题的目的是为回答“您有DOS行结尾”的日常问题提供答案,这样我们就可以简单地将它们作为本问题的副本关闭,而不必重复同样的答案

注意:这不是任何现有问题的重复。本问答的目的不仅仅是提供一个“运行此工具”的答案,而且是解释问题,这样我们就可以在这里向任何人提出相关问题,他们就会清楚地解释为什么在这里提出这些问题,以及运行此工具以解决他们的问题。我花了几个小时阅读了所有现有的问答,它们都缺乏对问题的解释、可用于解决问题的替代工具和/或可能解决方案的优缺点/注意事项。此外,他们中的一些人已经接受了非常危险的答案,永远不应该使用

现在回到典型问题,该问题将导致此处的推荐:

我有一个包含1行的文件:

what isgoingon
当我使用这个awk脚本来反转字段的顺序时:

awk '{print $2, $1}' file
我希望看到的不是输出:

isgoingon what
我得到了应该在行尾的字段,该字段出现在行首,覆盖了行首的一些文本:

 whatngon
或者我将输出分成两行:

isgoingon
 what

问题可能是什么?我该如何解决它?

问题是,您的输入文件使用DOS的
CRLF
行结尾,而不是UNIX的
LF
行结尾,并且您正在运行UNIX工具,因此
CR
仍然是UNIX工具操作的数据的一部分
CR
通常用
\r
表示,当您在文件上运行
cat-vE
,而
LF
\n
时,可以将其视为control-M(
^M
),并与
cat-vE一起显示为
$

因此,您的输入文件实际上不仅仅是:

what isgoingon
实际上是:

what isgoingon\r\n
正如您在cat-v上看到的那样:

$ cat -vE file
what isgoingon^M$
od-c

$ od -c file
0000000   w   h   a   t       i   s   g   o   i   n   g   o   n  \r  \n
0000020
因此,当您在文件上运行一个UNIX工具,如awk(它将
\n
视为行尾)时,
\n
会被读取行的行为消耗掉,但这会留下以下两个字段:

<what> <isgoingon\r>
awk将打印
isgoingon
,然后在打印
what
之前将光标返回到行的开头,这就是为什么
what
会覆盖
isgoingon
的开头

要解决此问题,请执行以下任一操作:

dos2unix file
sed 's/\r$//' file
awk '{sub(/\r$/,"")}1' file
perl -pe 's/\r$//' file
显然,
dos2unix
在某些UNIX变体(例如Ubuntu)中被称为
frodos

如果您决定像通常建议的那样使用
tr-d'\r'
,请小心,因为这将删除文件中的所有
\r
,而不仅仅是每行末尾的那些

请注意,GNU awk将允许您通过适当设置
RS
来解析具有DOS行结尾的文件:

gawk -v RS='\r\n' '...' file
但是其他AWK将不允许这样做,因为POSIX只要求AWK支持单个字符RS,而大多数其他AWK将悄悄地将
RS='\r\n'
截断为
RS='\r'
。您可能需要添加
-v BINMODE=3
,以便gawk甚至可以看到
\r
s,因为底层C原语将在某些平台上剥离它们,例如cygwin

需要注意的一点是,由Excel等Windows工具创建的CSV将使用
CRLF
作为行尾,但可以在CSV的特定字段中嵌入
LF
s,例如:

"field1","field2.1
field2.2","field3"
事实上:

"field1","field2.1\nfield2.2","field3"\r\n
因此,如果您只是将
\r\n
s转换为
\n
s,则无法再将字段内的换行符与换行符区分为换行符,因此如果您要这样做,我建议首先将所有字段内换行符转换为其他换行符,例如,这会将所有字段内的
LFs
转换为制表符,并将所有行尾
CRLF
s转换为
LF
s:

gawk -v RS='\r\n' '{gsub(/\n/,"\t")}1' file

在没有GNU awk作为练习的情况下进行类似操作,但在其他awk中,它涉及到在读取时不以
CR
结尾的行的组合。

问题是,您的输入文件使用DOS行的
CRLF
结尾,而不是UNIX行的
LF
结尾,并且您正在运行UNIX工具,因此
CR
仍然是UNIX工具操作的数据的一部分
CR
通常用
\r
表示,当您在文件上运行
cat-vE
,而
LF
\n
时,可以将其视为control-M(
^M
),并与
cat-vE一起显示为
$

因此,您的输入文件实际上不仅仅是:

what isgoingon
实际上是:

what isgoingon\r\n
正如您在cat-v上看到的那样:

$ cat -vE file
what isgoingon^M$
od-c

$ od -c file
0000000   w   h   a   t       i   s   g   o   i   n   g   o   n  \r  \n
0000020
因此,当您在文件上运行一个UNIX工具,如awk(它将
\n
视为行尾)时,
\n
会被读取行的行为消耗掉,但这会留下以下两个字段:

<what> <isgoingon\r>
awk将打印
isgoingon
,然后在打印
what
之前将光标返回到行的开头,这就是为什么
what
会覆盖
isgoingon
的开头

要解决此问题,请执行以下任一操作:

dos2unix file
sed 's/\r$//' file
awk '{sub(/\r$/,"")}1' file
perl -pe 's/\r$//' file
显然,
dos2unix
在某些UNIX变体(例如Ubuntu)中被称为
frodos

如果您决定像通常建议的那样使用
tr-d'\r'
,请小心,因为这将删除文件中的所有
\r
,而不仅仅是每行末尾的那些

请注意,GNU awk将允许您通过适当设置
RS
来解析具有DOS行结尾的文件:

gawk -v RS='\r\n' '...' file
但是其他AWK将不允许这样做,因为POSIX只要求AWK支持单个字符RS,而大多数其他AWK将悄悄地将
RS='\r\n'
截断为
RS='\r'
。您可能需要添加
-v BINMODE=3
,以便gawk甚至可以看到