^M (\r) 和 ^K (\v) 的命令行文本 find/replace

Command line text find/replace for ^M (\r) and ^K (\v)

我正在尝试编写一个 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。

以Windows行结束,你想删除^M(或\r或回车return),但你想用换行符替换^K,它似乎。

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

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

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

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

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


Actually, I need to replace both of these with a newline.

这更容易:调用 tr 即可完成工作:

tr '' '' < article_filemakerExport.xml > tmp.$$ &&
mv tmp.$$ article_filemakerExport.xml || rm -f tmp.$$

或者,如果您愿意:

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

我认为 control-K 没有 \z 风格的符号,但我愿意学习其他方式(可能是垂直制表符,\v)。

(在 Ed Morton 的提示处添加了 &&|| rm -f tmp.$$ 命令。)


部分控制字符列表

 C Oct Dec Hex Unicode Name
\a 07   7  07  U+0007 BELL
\b 10   8  08  U+0008 BACKSPACE
\t 11   9  09  U+0009 HORIZONTAL TABULATION
\n 12  10  0A  U+000A LINE FEED
\v 13  11  0B  U+000B VERTICAL TABULATION
\f 14  12  0C  U+000C FORM FEED
\r 15  13  0D  U+000D CARRIAGE RETURN

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

dos2unix <article_filemakerExport.xml | tr '35' '\n\n'

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'创建一个垂直制表符(^K$'' 也可以),$'\r' CR(^M),$'\n' 换行符)并传递 结果文字sed.
  • \\n 导致文字 \ 后跟文字换行符 - BSD sed 要求替换字符串中的文字换行符被 \ 转义(并且不'支持转义码\n).

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

注意:看起来您的问题至少部分源于假设 BSD sed 与 GNU sed 的工作方式相同,不幸的是,情况并非如此: 有许多细微的和不那么细微的区别 - 请参阅

  • -i 选项缺少参数导致 sed 将您的 程序 解释为 -i 参数,并且您的 文件名作为程序。由于您的文件名以 a 开头,sed 看到了 a (追加文本)命令,并在文件名的其余部分上窒息(因为它不是有效的 a 命令) .
  • 即使修复缺少的 -i 选项参数也不会使命令工作,原因如上(简而言之:不支持 control-char.escape sequences),还有你试图将垂直制表符表示为字符串 ^K(在 GNU sed 中你可以直接使用 \v)。