这个问题的目的是为日常问题提供一个答案,答案是“你有DOS行结束”,所以我们可以简单地将它们作为这个副本closures,而不必重复相同的答案和恶心 。
注意: 这不是任何现有问题的重复 。 这个问答的目的不仅仅是提供一个“运行这个工具”的答案,而且是为了解释这个问题,这样我们就可以在这里指出任何有相关问题的人,他们也会find一个明确的解释,说明他们为什么被指出来作为运行的工具来解决他们的问题。 我花了数小时阅读所有现有的问答,他们都缺乏对问题的解释,可以用来解决问题的替代工具,和/或可能的解决scheme的优点/缺点/警告。 还有一些人已经接受了只是非常危险的答案,不应该被使用。
现在回到可能导致转介的典型问题 :
join两个文件的第一列
文件格式:使用awk NRvariables混淆
使用Linux删除短于4个字符的单词
用逗号分隔多行代码(Perl / Sed / AWK)
如何在使用awk的文件模式之后打印5个连续的行
what isgoingon
当我使用这个awk脚本打印它来颠倒字段的顺序时:
awk '{print $2,$1}' file
而不是看到我期望的输出:
isgoingon what
我得到应该在行尾的字段出现在行首,覆盖行首的一些文本:
whatngon
或者我把输出分成两行:
isgoingon what
有什么问题,我该如何解决?
如何使用AWK颠倒字段的顺序?
计算基于时间的指标(每小时)
AWK中的多分裂
用sed打印每个匹配模式的第一行
如何仅在重复行的末尾添加连续数字
问题在于你的输入文件使用的是CRLF DOS行结尾,而不是仅仅是LF的UNIX行尾,而你正在运行一个UNIX工具,所以CR仍然是UNIX工具正在运行的数据的一部分。 CR通常用r表示,并且在LF为n在文件上运行cat -vE时可以看作是一个control-M( ^M ),并且显示为$ with cat -vE 。
所以你的输入文件不是真的只是:
what isgoingon
其实是:
what isgoingonrn
正如你可以看到与cat -v :
$ cat -vE file what isgoingon^M$
和od -c :
$ od -c file 0000000 whatisgoingon r n 0000020
所以当你在文件上运行一个像awk这样的UNIX工具(把n作为行结尾)时, n会被读取行消耗掉,但是会留下2个字段:
<what> <isgoingonr>
请注意第二个字段末尾的r 。 r表示Carriage Return符,实际上是将光标返回到行首的指令,所以当你这样做的时候:
print $2,$1
awk将打印isgoingon ,然后将光标返回到行的开始,然后打印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' ,那么要小心,因为这会删除文件中的所有文件,而不是每行结尾的文件。
请注意,GNU awk将让您通过简单地设置RS解析具有DOS行结尾的文件:
gawk -v RS='rn' '...' file
但是其他的awks不允许这样做,因为POSIX只需要awks来支持单个字符RS,而其他大多数awks都会静静地截断RS='rn'到RS='r' 。 您可能需要为gawk添加-v BINMODE=3来查看r s,因为底层的C原语会在某些平台上剥离它们,例如cygwin。
需要注意的一点是,像Excel这样的Windows工具创建的CSV将使用CRLF作为行尾,但可以将LF嵌入到CSV的特定字段中,例如:
"field1","field2.1 field2.2","field3"
是真的:
"field1","field2.1nfield2.2","field3"rn
所以如果您只是将rn s转换为n s,则您不能再将换行符中的换行符作为换行结束符,因此如果您想这样做,我建议先将所有的换行符换行转换为其他的换行符,例如,这会将所有内部字段LFs转换为制表符,并将所有结束CRLF的行转换为LF s:
gawk -v RS='rn' '{gsub(/n/,"t")}1' file
在没有GNU awk的情况下进行类似的练习只是一个练习,但是在其他awk中,它涉及到在读取时不结束CR行。
运行dos2unix 。 虽然你可以用自己编写的代码来操作行结尾,但Linux / Unix世界中已经存在的实用程序已经为你做了这些工作。
如果在Fedora系统上, dnf install dos2unix会把dos2unix工具放在适当位置(不应该安装)。
Debian系统有一个类似的dos2unix deb软件包。
从编程的角度来看,转换很简单。 搜索文件中的所有字符以获取序列rn并将其替换为n 。
这意味着使用几乎所有可以想象的工具,都有几十种从DOS转换到Unix的方法。 一个简单的方法就是使用命令tr ,只要简单地用r替换就可以了!
tr -d 'r' < infile > outfile
您可以在PCRE中使用R 简写字符类来处理未知行尾的文件。 在Unicode或其他平台上,还有更多线路需要考虑。 R表单是来自Unicode联合体的推荐字符类,用于表示所有形式的通用换行符。
所以,如果你有一个额外的,你可以找到并删除正则表达式s/R$/n/将标准化行结束的任何组合n 。 或者,您可以使用s/R/n/g来捕获任何“行结束”的概念并将其标准化为n字符。
鉴于:
$ printf "whatrisgoingonrn" > file $ od -c file 0000000 what risgoingon r n 0000020
Perl和Ruby以及PCRE的多数风格实现R结合字符串断言的结束$ (多行模式下的行尾):
$ perl -pe 's/R$/n/' file | od -c 0000000 what risgoingon n 0000017 $ ruby -pe '$_.sub!(/R$/,"n")' file | od -c 0000000 what risgoingon n 0000017
(注意两个单词之间的r是正确的单独)
如果您没有R您可以在PCRE中使用相同的(?>rn|v) 。
有了POSIX的直接工具,你最好的选择可能就是这样:
$ awk '{sub(/r$/,"")} 1' file | od -c 0000000 what risgoingon n 0000017
事情有点工作(但知道你的局限性):
tr删除所有r即使在另一个上下文中使用(授予r很少使用,而且XML处理要求r被删除,所以tr是一个很好的解决方案):
$ tr -d "r" < file | od -c 0000000 whatisgoingon n 0000016
GNU sed工作,但不支持POSIX sed因为r和x0D在POSIX上不受支持。
GNU sed only:
$ sed 's/x0D//' file | od -c # also sed 's/r//' 0000000 what risgoingon n 0000017
Unicode正则表达式指南可能是对“新行”进行明确处理的最佳选择。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。