Bash 将DOS ^M字符转换为Unix格式失败
我正在从一些文件中删除DOS^m字符。如果在单个文件上运行此sed行,它会按预期删除字符:Bash 将DOS ^M字符转换为Unix格式失败,bash,sed,Bash,Sed,我正在从一些文件中删除DOS^m字符。如果在单个文件上运行此sed行,它会按预期删除字符: $ sed -i 's/^M//g' somefile.txt 但是,如果我在for循环中从文件列表中拉取同一行,它将不起作用: $ for i in `cat list`; do sed -i 's/^M//g' $i; done 请注意,我可以应用其他命令而不是sed,它们按顺序在每个文件上按预期执行。此外,不会抛出错误(甚至不会抛出代码,因为echo$?返回0)。我也试着引用$I 根据评论中的建
$ sed -i 's/^M//g' somefile.txt
但是,如果我在for循环中从文件列表中拉取同一行,它将不起作用:
$ for i in `cat list`; do sed -i 's/^M//g' $i; done
请注意,我可以应用其他命令而不是sed,它们按顺序在每个文件上按预期执行。此外,不会抛出错误(甚至不会抛出代码,因为echo$?
返回0)。我也试着引用$I
根据评论中的建议,我尝试使用dos2unix,方法是:
$ for i in `cat list`; do dos2unix $i; done
但一切都没有改变。直接在单个文件上使用dos2unix很好。如果我的列表文件不好,我希望至少会抛出一个错误代码…首先,我认为
sed
不理解^M
回车。它应该是\r
此外,由于UNIX中的文件名可以包含bash的默认字段分隔符,我建议改用while read循环:
while read -r file ; do
sed -i 's/\r//' "$file"
done < list
顺便说一句,
g
选项在sed命令中没有意义,因为\r
每行只出现一次。这就是为什么我省略了它。答案是我在运行命令时输入^M字符时不够小心。正如其他文章所解释的,有必要键入ctrl-v、ctrl-m以输入^m作为单个控制字符
我的问题是,我假设如果一开始是这样输入的,那么在那之后高亮显示并粘贴它就可以了,但对于我正在使用的终端模拟器(guake、tmux)来说,情况并非如此。不,这完全可以按书面方式工作(假设for循环适用于您所说的其他命令;文件名的详细信息或列表文件的格式可能会把事情搞砸,但这并不取决于您在每个文件上运行的命令)。还有一些不同。我会在读取并引用“$I”时将for循环更改为
但除此之外,很难猜出哪里出了问题。您是否复制/粘贴了字符^
和M
,或者在第二种情况下实际创建了一个Ctrl-M字符。我打赌是复制/粘贴。此外,如果您的文件很大,您可以加快替换速度(稍微)但是将匹配锚定到行的末尾,即sed的/^M$/'
。最后,您的系统没有dos2unix文件
?祝您好运。与每天发布和回答的垃圾相比,这是一个完全可以接受的问题(IHMO)。你的问题已经扩展到我们的评论,在我的书中,这始终是一些值得帮助的标志;-)请随意发表你的评论作为答案,并在期限到期时接受它。其他人可能会发表相反的评论。让计票决定;-)祝大家好运@Shelleter,如果经过足够的编辑,不再让人们对实际问题不感兴趣(也不再将误导性内容作为问题的一部分),我可以看到这篇文章保持开放。然而,事实上,这只是一种误导。sed
确实理解的^M
是一个单一字符,在大多数unix环境中是通过使用^V转义创建的,即按Ctrl-V
然后按Ctrl-M
。这将显示为^M
,与键入为^
和M
的两个单独字符不同。有一些unix实用程序确实理解2字符^M
是Ctrl-M
,stty
(我认为)是最常见的。这个问题看起来像是按字面意思键入的^
,M
。也许这就是根本原因在评论中,O.P.表示他意识到并使用了ctrl-v、ctrl-m,但后来意识到他并不一致,在创建for循环时使用了复制/粘贴。我对你的优秀答案的评论是,把记录直接放在^
M
vs^M
;-)
find PATH_TO_FILES -type f -name 'NAME' ... -exec sed -i 's/\r//' {} \;