Jak tr tłumaczy jedno słowo na drugie?

9

Mam plik, ma.txtktóry zawiera dane wyjściowe ls -l; po uruchomieniu trpolecenia ( tr "nik-pc" "root") otrzymuję następujące dane wyjściowe:

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

W pierwszym wierszu zastąpił „nik” słowem „too”, a pisownia „Desktop” zmieniła się w „Desottt”.

Dlaczego to? Co za tym stoi logika?

Manish Bharti
źródło
3
info coreutils 'tr invocation'mówi szczegółowo, co trrobi.
Nephente
4
A tak przy okazji, co próbujesz zrobić? Polecenie było dokładnie to, co powiedział to zrobić, ale myślę, że rzeczywiście chcesz wymienić nik-pcz root?
Kos
3
Pierwszym krokiem jest zawsze sprawdzenie strony podręcznika man.
Mostafa Ahangarha
1
@DavidZ: Zauważ, że nrównież jest w k-pzakresie. Wynik pojawienia się znaku więcej niż raz w pierwszym zestawie nie jest określony przez POSIX.
hmakholm opuścił Monikę
1
Myślę, że to, czego naprawdę potrzebujesz, to sedpolecenie ... ls -l | sed 's/nik-pc/root/'zrobi to, co chcesz. trsłuży do konwersji pojedynczych znaków - np. małe i wielkie litery lub przesunięcie wiersza w stylu dos (\ r) do stylu uniksowego (\ n) lub coś w rodzaju zastąpienia wszystkich ukośników odwrotnych (Windows) ukośnikami. Może także usuwać „niechciane” znaki, np. wszystkie cyfry lub wszystkie wielkie litery.
Baard Kopperud

Odpowiedzi:

16

trtłumaczy łańcuch znaków. Przeszukuje litery z pierwszego zestawu i zastępuje je literami z drugiego zestawu.

Miałeś nik-pcjako pierwszy zestaw. trrozszerza tę k-pczęść na wszystkie litery w zakresie od „k” do „p”, więc zestaw jest równy niklmnopc.

Twój drugi zestaw był root.

Co trteraz robi to, aby szukać wszystkie wystąpienia pierwszego znaku w (analizowany) pierwszego zestawu i wymienić je na pierwszy znak drugiego zestawu. Gdy w zestawie 2 nie ma już żadnej postaci, po prostu powtarza swój ostatni znak. Tabela poniżej:

n --> r
i --> o
k --> o
l --> t
m --> t
n --> t
o --> t
p --> t
c --> t

Teraz jest jasne, dlaczego np. „Desktop” staje się „Desottt”. Zachowanie jest w pełni poprawne i zamierzone w ten sposób.


To, czego szukasz, można osiągnąć za pomocą sed:

sed 's/nik-pc/root/g' ma.txt

Składnia jest następująca:

sed 's/SEARCH_PATTERN/REPLACE_STRING/FLAGS' INPUT_FILE

Pozwalamy więc wyszukiwać wzór „nik-pc” i zastępujemy całe dopasowanie słowem „root”. Musimy dodać flagę „g”, aby umożliwić zastępowanie globalne. Bez tego zastąpiłoby tylko każde pierwsze dopasowanie w linii.

Bajt Dowódca
źródło
Ta tabela ze strzałkami jeszcze bardziej wyjaśnia wyjaśnienie, podoba mi się to. + 1-ed. Użytkownik prawdopodobnie mógłby zrobić coś podobnego za pomocąprintf "A\nB\nC\n" | tr 'ABC' '12'
Sergiy Kolodyazhnyy 17.03.16
18

trsłuży do tłumaczenia znaków, a nie do pełnych słów. Może tłumaczyć zestawy. W twoim przykładzie masz „nik-pc” jako znaki pierwszej kolekcji, a „root” to kolejny. W rzeczywistości k-pjest zakresem, więc obejmuje wszystkie znaki od k do p. Będzie pasował do znaków jeden po drugim, więc n będzie tłumaczyć na r, i do o, k do o, i cokolwiek innego poza 4. char będzie t. Właśnie dlatego przetłumaczono „Desktop” na „Desottt”

Możesz to lepiej zobaczyć w tym przykładzie:

$ echo "ABCDEF" | tr "ABCDEF"  "12"                            
122222

Tutaj widać, że tr zestaw 1 ma D w pozycji 4. Ale zestaw 2 nie ma pozycji 4, więc użyje ostatniej pozycji, zestaw 2 musi się przełożyć.

To, co robisz, polega na tłumaczeniu jednego słowa na drugie. To, co chcesz zrobić, to użyć bardziej zaawansowanego narzędzia, takiego jak sedlub awk.

Na przykład,

$ ls -l /etc/passwd | awk '{gsub(/root/,"TEST");print}'        
-rw-r--r-- 1 TEST TEST 2575 Feb 29 12:30 /etc/passwd
Sergiy Kolodyazhnyy
źródło
6
LUB sed s / nik-pc / root / g ma.txt> ma2.txt
Bruni
1
Byłeś znacznie szybszy ode mnie @Serg ...: P
Byte Commander
2
@ByteCommander Mogłem wygrać szybko, ale myślę, że twoja odpowiedź wygrywa pod względem jakości
Sergiy Kolodyazhnyy