假设我有一个使用 Unix EOL 格式创建的文件。现在,在将该文件发送到 Windows 之前,必须进行 EOL 转换。
我需要在 bash 中执行此操作,这是我目前所做的:
为了简单起见,假设我的文件名为 file_linux.txt 并且它给出以下输出:
cat -A file_linux.txt
first line$
second line$
third line$
file file_linux.txt
file_linux.txt: ASCII text
因此,我似乎唯一需要做的就是在$象征。
我的想法是使用 sed 来替换每一个$和\r$以下方式:
sed 's/$/\r$/g' file_linux.txt | cat -A
first line^M$$
second line^M$$
third line^M$$
如您所见,我将 sed 的输出通过管道传输到 cat -A。我期望$替换为\r$但似乎我有一个额外的$在最后。
另外,如果我将这个 sed 传送给普通的 cat,我会得到这个奇怪的结果:
sed 's/$/\r$/g' file_linux.txt | cat
$irst line
$econd line
$hird line
当我将它通过管道传输到一个文件时,它似乎不是一个 Windows 文件:
sed 's/$/\r$/g' file_linux.txt | file -
file_linux.txt: ASCII text, with CR, LF line terminators
因为当我对从 Windows 系统导入的文件执行此操作时,我得到以下输出:
file_from_win.txt: ASCII text, with CRLF line terminators
另外,我正在尝试这个,结果发现删除第二个$在 sed 中解决了该问题:
sed 's/$/\r/g' file_linux.txt | file -
file_linux.txt: ASCII text, with CRLF line terminators
sed 's/$/\r/g' file_linux.txt | cat -A
first line^M$
second line^M$
third line^M$
我想知道为什么最后这个方法有效,sed 中第一个和第二个斜杠之间的字符不应该被第二个和第三个斜杠之间的字符替换吗?我的意思是,如果是这样的话,在最后一个例子中,我会有一个文件\r代替$以前是这样的,但事实并非如此。\r之前刚刚添加$。
我在 Ubuntu 20.04.3 LTS 上完成了此操作。
非常感谢您的帮助!
答案1
您$
在命令的 LHS 上匹配的不是字符 - 它是一个正则表达式元字符代表行尾(有时称为行锚- 属于一个较大的类别零长度断言)。
在 sed 替换命令中,s/pattern/replacement/
只有 LHSpattern
被解释为正则表达式。像^
和$
这样的字符表示 LHS 上的锚点,在 RHSreplacement
文本中是纯文字字符。事实上,RHS 上的所有内容都是文字,但以下可能的情况除外反向引用:
替换可以包含 \n(n 是 1 到 9 之间的数字,含 1 和 9)引用,这些引用指的是第 n 个 \( 和其匹配的 \ 之间的匹配部分。此外,替换可以包含未转义的 & 字符,这些字符引用模式空间的整个匹配部分。
仅供参考,虽然和sed 's/$/\r/
是sed 's/\r$//
将行尾从 UNIX 转换为 DOS 和从 DOS 转换为 UNIX 的完美方式(顺便说一句,您不需要修饰符g
- 根据定义,一行只能有一个结尾),但也有专用实用程序unix2dos
和可从Ubuntu 存储库中的软件包dos2unix
中获得。除了行尾,它们还将处理文件编码和字节顺序标记 (BOM) 等内容。dos2unix
universe