Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a file ma.txt and it contains the output of ls -l; when I run the tr 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?

share|improve this question
3  
info coreutils 'tr invocation' tells you en detail what tr does. – Nephente Mar 17 at 14:49
4  
What are you trying to do by the way? The command did exactly what you told it to do, but I guess you actually want to replace nik-pc with root? – kos Mar 17 at 14:51
3  
First step is always to check man page of the command. – Mostafa Ahangarha Mar 17 at 15:06
1  
@DavidZ: Note that n is also in the k-p range. The result of a character appearing more than once on the first set is unspecified by POSIX. – Henning Makholm Mar 17 at 20:35
1  
I 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. – Baard Kopperud Mar 17 at 23:26
up vote 16 down vote accepted

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.

share|improve this answer
    
That 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' – Serg Mar 17 at 15:09

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
share|improve this answer
6  
OR sed s/nik-pc/root/g ma.txt > ma2.txt – Bruni Mar 17 at 15:02
1  
You were much faster than me @Serg... :P – Byte Commander Mar 17 at 15:08
2  
@ByteCommander I may have won in speed, but I think your answer wins in quality – Serg Mar 17 at 15:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.