命令行文本查找/替换^ M(\ r)和^ K(\ v)

时间:2015-02-24 18:16:20

标签: macos bash text replace sed

我试图编写一个shell脚本(其中包括)将用新行替换windows行结尾(^M)和垂直标签(^K)。 Sed看起来像是使用的工具,但我无法得到它。我不明白为什么这不会起作用..

$ sed -i 's/^K/\n/g' article_filemakerExport.xml 
sed: 1: "article_filemakerExport ...": command a expects \ followed by text

注意:我正在使用Mac。

3 个答案:

答案 0 :(得分:4)

在Windows行结束时,您想要删除^ M(或\r或回车符),但是您想要用换行替换^ K,看起来就像。

我使用的命令是tr,两次。

tr -d '\r' < article_filemakerExport.xml | tr '\13' '\12' > tmp.$$ &&
mv tmp.$$ article_filemakerExport.xml || rm -f tmp.$$

鉴于一个操作是删除而另一个操作是替换,我不认为您可以将这些操作合并为一个tr调用。如果您担心链接等,可以使用cp tmp.$$ article_filemakerExport.xml; rm -f tmp.$$

您还可以使用dos2unix将CRLF转换为NL行结尾,而不是tr

请注意tr是一个纯粹的过滤器;它只读取标准输入,只写入标准输出。它不直接读取或写入文件。


  

实际上,我需要用换行符替换这两个。

这更容易:tr的单一调用将完成这项工作:

tr '\13\15' '\12\12' < article_filemakerExport.xml > tmp.$$ &&
mv tmp.$$ article_filemakerExport.xml || rm -f tmp.$$

或者,如果您愿意:

tr '\13\r' '\n\n' < article_filemakerExport.xml > tmp.$$ &&
mv tmp.$$ article_filemakerExport.xml || rm -f tmp.$$

我认为没有#{1}} - 控制-K的风格符号,但我愿意另外学习(它可能是垂直标签,\z )。

(在提示Ed Morton时添加了\v&&命令。)


控制字符的部分列表

|| rm -f tmp.$$

您可以在Unicode站点(http://www.unicode.org/charts/PDF/U0000.pdf)找到一组完整的控制字符。毫无疑问,还有许多其他可能的地方。

答案 1 :(得分:1)

dos2unix <article_filemakerExport.xml | tr '\013\015' '\n\n'

答案 2 :(得分:1)

BSD(OS X)sed解决方案,由ANSI C-quoted bash strings协助:

sed -i "" $'s/\r$/\\\n/g; s/\v/\\\n/g' article_filemakerExport.xml

注意:

  • BSD sed - 与GNU sed不同 - 要求带有-i选项的参数;因此,为了表明应该创建 no 备份文件,必须传递空字符串"") - 请参阅下文,了解如何解释您遇到的错误
  • 该命令将\r\n替换为\n\n而不是\n,这是我理解你想要的(只获得\n,只需将第二个替换字符串设为空;要取代\r,即使没有直接\n,请在$之后删除\r

以下是样本输入的概念证明:

$ sed  $'s/\r$/\\\n/g; s/\v/\\\n/g' <<<$'one\vtwo\r\nthree\nfour'
one
two

three
four

(上面输出中的所有换行符都是\n。)

  • 需要ANSI C引用的字符串($'...')来弥补BSD sed中对转义序列的支持不足:shell创建所需的控制字符($'\v'创建一个垂直制表符({ {1}}; ^K也会工作),$'\13' CR($'\r'),^M换行符)并传递结果文字$'\n'
  • sed会生成一个文字\\\n后跟一个文字换行符 - BSD \要求替换字符串中的文字换行符为sed - 转义(并且不会#39} ; t支持转义码\)。

至于为什么你的命令不起作用

注意:看起来您的问题至少部分源于假设BSD \n与GNU sed的工作方式相同,但遗憾的是,并非如此:有很多微妙而不是那么微妙的差异 - 见https://stackoverflow.com/a/24276470/45375

  • sed选项缺少的参数导致-i程序解释为sed参数,以及您的文件名作为该计划。由于您的文件名以-i开头,a看到了sed(附加文本)命令,并且在文件名的其余部分被阻塞(因为它不是有效的{{1}命令)。
  • 由于上面列出的原因(简而言之:不支持control-char。转义序列),即使修复丢失的a选项参数也不会使命令工作,也是你的尝试将垂直制表符表示为字符串a(在GNU -i中,您可以直接使用^K