How does tr translate one word to another?
Solution 1
tr
translates a string character-wise. It searches the letters from the first set and replaces them by those form the second set.
You had nik-pc
as first set. tr
expands the k-p
part in that to all letters in the range from "k" to "p", so the set is equal to niklmnopc
.
Your second set was root
.
What tr
now does is to search all occurrences of the first character in the (evaluated) first set and replace them with the first character of the second set. When there is no more character in set 2, it simply repeates its last character. See the table below:
n --> r
i --> o
k --> o
l --> t
m --> t
n --> t
o --> t
p --> t
c --> t
So now it's clear why e.g. "Desktop" becomes "Desottt". The behaviour is fully correct and intended this way.
What you're looking for instead can be achieved using sed
:
sed 's/nik-pc/root/g' ma.txt
The syntax is this:
sed 's/SEARCH_PATTERN/REPLACE_STRING/FLAGS' INPUT_FILE
So we let it search for the pattern "nik-pc" and replace the entire match with "root". We need to add the "g" flag to enable global replacing. Without that, it would only replace each first match per line.
Solution 2
tr
is for translating characters, not for complete words. It can translate sets. In your example you have "nik-pc" as first collection chars, and "root" is another. In fact, k-p
is a range, so it includes all chars from k to p. It will match chars one by one, so n will translate to r, i to o, k to o, and whatever else beyond 4th char will be t. That's why you have "Desktop" translated to "Desottt"
You can see it more clearly in this example:
$ echo "ABCDEF" | tr "ABCDEF" "12"
122222
Here you can see tr
set 1 have D in position 4. But set 2 has no position 4, so it will use last position set 2 has to translate.
What you are doing is translating one word into another. What you want to do is use more advanced tool like sed
or awk
.
For instance,
$ ls -l /etc/passwd | awk '{gsub(/root/,"TEST");print}'
-rw-r--r-- 1 TEST TEST 2575 Feb 29 12:30 /etc/passwd
Related videos on Youtube
Manish Bharti
Updated on September 18, 2022Comments
-
Manish Bharti over 1 year
I have a file
ma.txt
and it contains the output ofls -l
; when I run thetr
command (tr "nik-pc" "root"
) I get this output: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
At line one it replaced "nik" with "too" and the spelling of "Desktop" became "Desottt".
Why is this? What is logic behind it?
-
Nephente about 8 years
info coreutils 'tr invocation'
tells you en detail whattr
does. -
Mostafa Ahangarha about 8 yearsFirst step is always to check man page of the command.
-
jkinter about 8 yearsThe output you posted is actually a bit inconsistent, because your
n
s are translated tot
s instead ofr
s as they should be.. Just to be sure, is there any chance you rantr "nik-pc" "toot"
instead? -
hmakholm left over Monica about 8 years@DavidZ: Note that
n
is also in thek-p
range. The result of a character appearing more than once on the first set is unspecified by POSIX. -
Joshua about 8 yearslol man so funny I so saw where this was going from the title
-
Baard Kopperud about 8 yearsI think what you really need, is the
sed
command...ls -l | sed 's/nik-pc/root/'
would do what you want.tr
is for converting single characters - eg. lower-case to upper-case, or dos-style lineshift (\r) to Unix-style (\n), or something like replacing all backslashes (Windows) with slashes. It can also delete "unwanted" characters, eg. all numbers or all upper-case letters. -
jkinter about 8 years@HenningMakholm oh, silly me, I missed that
n
was in the range.
-
-
Bruni about 8 yearsOR sed s/nik-pc/root/g ma.txt > ma2.txt
-
Byte Commander about 8 yearsYou were much faster than me @Serg... :P
-
Sergiy Kolodyazhnyy about 8 yearsThat table with arrows makes the explanation even clearer, I like that. +1-ed . A user could probably make something similar with
printf "A\nB\nC\n" | tr 'ABC' '12'
-
Sergiy Kolodyazhnyy about 8 years@ByteCommander I may have won in speed, but I think your answer wins in quality