在 WSL 中替换行尾时 sed 表现异常

sed behaving strangely when replacing line ends in WSL

我正在尝试使用 sed 在每一行末尾为目录中的所有 .txt 文件添加一些文本。这是我使用的确切命令:find . -name "*.txt" -exec sed -i 's/$/:orig/' {} +

预计:

https://pbs.twimg.com/media/EUr539_UMAAFqZM.jpg:orig
https://pbs.twimg.com/media/ENTrymcUwAAnd6_.jpg:orig
https://pbs.twimg.com/media/EIzzcrFUYAAgfUo.jpg:orig

这也是我在笔记本电脑 Linux Mint 19.2 中 运行 时实际得到的结果。但是当我在我的 Windows PC 上尝试它时,运行ning sed through Ubuntu 在 WSL 中,我得到的是:

https://pbs.twimg.com/media/EUr539_UMAAFqZM.jpg
:orig
https://pbs.twimg.com/media/ENTrymcUwAAnd6_.jpg
:orig
https://pbs.twimg.com/media/EIzzcrFUYAAgfUo.jpg:orig

如果我 cat 有问题的文件仍然在 Ubuntu 终端中,则显示的内容更像这样(有一些奇怪的空白使其看起来像 SO 中的列,但通常它们看起来都很混乱):

:orig://pbs.twimg.com/media/EUr539_UMAAFqZM.jpg                                                                         :orig://pbs.twimg.com/media/ENTrymcUwAAnd6_.jpg                                                                         https://pbs.twimg.com/media/EIzzcrFUYAAgfUo.jpg:orig

我知道 Windows 和 Linux 文本的格式不同,尤其是那一行结尾有问题,但我不确定这在这里是否重要。

任何人都可以阐明这种行为吗?我怎样才能使命令的行为一致?

问题是您的文件以 CRLF 结尾,但 WSL sed 仅使用 LF 和行结束。如果您 知道 它是 CRLF 风格,您可以通过三个步骤解决这个问题文件:

  • 去掉 CR;
  • 做你的改变;
  • CR 放回去。

那会是这样的:sed -i -e 's/\r$//' -e 's/$/:orig/' -e 's/$/\r/'

但是,这不适用于 UNIX 风格的文件,因为第一次替换什么都不做,但第三次替换会在每行的末尾放置一个 CR 字符,即使它最初不存在。如果您想要对两种 类型的文件都有效的东西,应该这样做:

sed -E 's/(\r)?$/:orig/'

这个捕获了行尾可选的CR,并放回替换中(如果不在原行,则不会放回) .