我可以使用“sed”来像“tr”一样翻译字符吗?

我可以使用“sed”来像“tr”一样翻译字符吗?

我想用另一组中的相应字符替换一组字符,如下所示:

original set: ots
"target" set: u.x

foobartest → fuubar.ex.

像这样的翻译/音译是该命令的特色tr

$ echo 'foobartest' | tr 'ots' 'u.x'
fuubar.ex.

不幸的是,tr不支持像那样就地更改文件sed
我想使用sed这样我就不必重新发明临时文件的轮子。

答案1

sed具有至少在大多数实现中y一样工作的命令:tr

$ echo 'foobartest' | sed 'y/ots/u.x/'
fuubar.ex.

y命令是POSIXsed规范,所以它应该可以在任何平台上运行。

而且由于它是sed,您可以让它用其编辑后的版本替换文件,从而免除您麻烦的临时文件业务(前提是您的实现sed支持该-i选项,POSIX 未指定该选项):

$ sed -i 'y/ots/u.x/' some-file.txt

目前 BSD 实施sed 实际上并不反映tr某些极端情况下的行为

答案2

如果像你的情况一样,你要音译字符而不改变其大小(无论如何,像 GNU 这样的一些实现tr只支持单字节字符),你可以这样做:

tr 'ots' 'u.x' < file 1<> file

也就是说,tr覆盖文件本身。

sed -i这比几个帐户要好:

  • 它不需要额外的磁盘空间(除了一些稀疏文件,写时复制特殊情况)
  • 它保留 inode 编号、所有权、权限、ACL...
  • 它与符号链接一起工作正常,不会破坏硬链接
  • 它不会在被杀死时留下临时文件。

一个缺点是,如果它被中断,文件最终将被翻译一半(不过,在这种情况下,您可以再次运行它来完成它)。某些sed实现可以通过确保原始文件保持不变(除非命令成功)来正确处理该问题。

答案3

作为另一种选择,如果您的主要问题是缺乏对就地更改文件的支持,您可能会对sponge来自更多实用程序包

tr 'ots' 'u.x' < file | sponge file

将写入file,但仅打开file在输入完成后才打开进行写入。来自联机帮助页

sponge读取标准输入并将其写入指定文件。与 shell 重定向不同,sponge 在打开输出文件之前吸收所有输入。这允许构建读取和写入同一文件的管道。

除非您有无法保存在内存中的非常大的文件,否则sponge可能适合您。

相关内容