我有一个文件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
在第一行,它将“nik”替换为“too”,并将“Desktop”的拼写替换为“Desottt”。
这是为什么?这背后的逻辑是什么?
答案1
tr
用于翻译字符,而不是完整的单词。它可以翻译集合。在您的示例中,您有“nik-pc”作为第一个集合字符,而“root”是另一个。事实上,k-p
是一个范围,因此它包括从 k 到 p 的所有字符。它将逐个匹配字符,因此 n 将转换为 r,i 转换为 o,k 转换为 o,而第 4 个字符以外的任何其他字符都将是 t。这就是为什么您将“Desktop”翻译成“Desottt”
你可以在这个例子中更清楚地看到这一点:
$ echo "ABCDEF" | tr "ABCDEF" "12"
122222
在这里你可以看到tr
集合 1 在位置 4 处有 D。但是集合 2 没有位置 4,所以它将使用集合 2 必须翻译的最后一个位置。
你正在做的是将一个单词翻译成另一个单词。你需要做的是使用更高级的工具,例如sed
或awk
。
例如,
$ ls -l /etc/passwd | awk '{gsub(/root/,"TEST");print}'
-rw-r--r-- 1 TEST TEST 2575 Feb 29 12:30 /etc/passwd
答案2
tr
按字符转换字符串。它从第一组中搜索字母,并用第二组中的字母替换它们。
您有nik-pc
第一组。将其中的部分tr
扩展k-p
为从“k”到“p”范围内的所有字母,因此该集合等于niklmnopc
。
你的第二盘是root
。
现在要做tr
的是搜索(已评估的)第一组中第一个字符的所有出现位置,并将其替换为第二组的第一个字符。当第二组中没有其他字符时,它只会重复其最后一个字符。请参阅下表:
n --> r
i --> o
k --> o
l --> t
m --> t
n --> t
o --> t
p --> t
c --> t
现在很清楚为什么例如“Desktop”会变成“Desottt”。这种行为完全正确,而且是有意为之。
您正在寻找的内容可以通过以下方式实现sed
:
sed 's/nik-pc/root/g' ma.txt
语法如下:
sed 's/SEARCH_PATTERN/REPLACE_STRING/FLAGS' INPUT_FILE
因此我们让它搜索模式“nik-pc”,并将整个匹配替换为“root”。我们需要添加“g”标志以启用全局替换。如果没有这个标志,它只会替换每行的每个第一个匹配项。