tr 如何将一个词翻译成另一个词?

Man*_*rti 9 command-line tr

我有一个文件ma.txt,它包含的输出ls -l;当我运行tr命令 ( tr "nik-pc" "root") 时,我得到以下输出:

nik-pc@nik:~$ cat ma.txt 
total 52
drwxr-xr-x 2 nik-pc nik-pc 4096 Mar 11 11:33 Desktop
lrwxrwxrwx 1 nik-pc nik-pc    2 Mar  8 22:54 di -> hd
drwxr-xr-x 3 nik-pc nik-pc 4096 Mar 13 13:28 Documents
drwxr-xr-x 7 nik-pc nik-pc 4096 Mar 14 18:21 Downloads
drwxr-xr-x 2 nik-pc nik-pc 4096 Mar 11 09:39 dwhelper
-rw-r--r-- 1 nik-pc nik-pc 2134 Mar 13 17:40 hd
-rw-r--r-- 1 nik-pc nik-pc    3 Mar 13 15:34 m
-rw-r--r-- 1 nik-pc nik-pc    0 Mar 17 19:48 ma.txt
drwxr-xr-x 3 nik-pc nik-pc 4096 Mar 13 14:58 Music
drwxr-xr-x 2 nik-pc nik-pc 4096 Mar  5 12:30 Pictures
drwxr-xr-x 2 nik-pc nik-pc 4096 Mar  5 11:44 Public
drwxr-xr-x 2 nik-pc nik-pc 4096 Mar 13 15:58 sd
drwxr-xr-x 2 nik-pc nik-pc 4096 Mar  5 11:44 Templates
drwxr-xr-x 2 nik-pc nik-pc 4096 Mar  5 11:44 Videos
drwxr-xr-x 2 nik-pc nik-pc 4096 Mar 11 11:33 xdm-helper

nik-pc@nik:~$ tr "nik-pc" "root" < ma.txt 
tttat 52
drwxr-xr-x 2 too-tt too-tt 4096 Mar 11 11:33 Desottt
trwxrwxrwx 1 too-tt too-tt    2 Mar  8 22:54 do -> hd
drwxr-xr-x 3 too-tt too-tt 4096 Mar 13 13:28 Dttutetts
drwxr-xr-x 7 too-tt too-tt 4096 Mar 14 18:21 Dtwtttads
drwxr-xr-x 2 too-tt too-tt 4096 Mar 11 09:39 dwhetter
-rw-r--r-- 1 too-tt too-tt 2134 Mar 13 17:40 hd
-rw-r--r-- 1 too-tt too-tt    3 Mar 13 15:34 t
-rw-r--r-- 1 too-tt too-tt    0 Mar 17 19:48 ta.txt
drwxr-xr-x 3 too-tt too-tt 4096 Mar 13 14:58 Musot
drwxr-xr-x 2 too-tt too-tt 4096 Mar  5 12:30 Pottures
drwxr-xr-x 2 too-tt too-tt 4096 Mar  5 11:44 Pubtot
drwxr-xr-x 2 too-tt too-tt 4096 Mar 13 15:58 sd
drwxr-xr-x 2 too-tt too-tt 4096 Mar  5 11:44 Tetttates
drwxr-xr-x 2 too-tt too-tt 4096 Mar  5 11:44 Vodets
drwxr-xr-x 2 too-tt too-tt 4096 Mar 11 11:33 xdt-hetter
Run Code Online (Sandbox Code Playgroud)

在第一行,它用“too”替换了“nik”,“Desktop”的拼写变成了“Desottt”。

为什么是这样?背后的逻辑是什么?

Ser*_*nyy 18

tr用于翻译字符,而不是完整的单词。它可以翻译集合。在您的示例中,您将“nik-pc”作为第一个集合字符,而“root”是另一个。事实上,k-p是一个范围,所以它包括从 k 到 p 的所有字符。它将一一匹配字符,因此 n 将转换为 r,i 转换为 o,k 转换为 o,并且超出第 4 个字符的任何其他字符都将是 t。这就是为什么您将“桌面”翻译为“Desottt”

在这个例子中你可以更清楚地看到它:

$ echo "ABCDEF" | tr "ABCDEF"  "12"                            
122222
Run Code Online (Sandbox Code Playgroud)

在这里你可以看到第tr 1 组在第 4 位有 D。但第 2 组没有第 4 位,所以它将使用第 2 组必须平移的最后一个位置。

你正在做的是将一个词翻译成另一个词。您想要做的是使用更高级的工具,例如sedawk

例如,

$ ls -l /etc/passwd | awk '{gsub(/root/,"TEST");print}'        
-rw-r--r-- 1 TEST TEST 2575 Feb 29 12:30 /etc/passwd
Run Code Online (Sandbox Code Playgroud)

  • 或 sed s/nik-pc/root/g ma.txt &gt; ma2.txt (6认同)
  • @ByteCommander 我可能在速度上赢了,但我认为你的回答在质量上赢了 (2认同)

Byt*_*der 17

tr按字符转换字符串。它搜索第一组中的字母,并用第二组中的字母替换它们。

你有nik-pc作为第一组。tr将其中的k-p部分扩展为从“k”到“p”范围内的所有字母,因此该集合等于niklmnopc

你的第二盘是root

tr现在要做的是搜索(评估的)第一组中第一个字符的所有出现,并将它们替换为第二组的第一个字符。当集合 2 中没有更多字符时,它只是重复它的最后一个字符。见下表:

n --> r
i --> o
k --> o
l --> t
m --> t
n --> t
o --> t
p --> t
c --> t
Run Code Online (Sandbox Code Playgroud)

所以现在很清楚为什么例如“Desktop”变成“Desottt”。这种行为是完全正确的,并且是这样设计的。


可以使用sed以下方法实现您正在寻找的内容:

sed 's/nik-pc/root/g' ma.txt
Run Code Online (Sandbox Code Playgroud)

语法是这样的:

sed 's/SEARCH_PATTERN/REPLACE_STRING/FLAGS' INPUT_FILE
Run Code Online (Sandbox Code Playgroud)

所以我们让它搜索模式“nik-pc”并将整个匹配替换为“root”。我们需要添加“g”标志以启用全局替换。没有它,它只会替换每行的第一个匹配项。