Tr aralıklarının garip davranışı


10

Tr kullanırken garip davranış gösteren belirli bir sunucu var. Çalışan bir sunucudan bir örnek:

-bash-3.2$ echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
1234567890
-bash-3.2$

Bu benim için çok mantıklı.

Ancak bu 'özel' sunucudan:

[root@host~]# echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
abcdefghijklmnpqrstuvwxyz1234567890

Gördüğünüz gibi, tüm küçük harflerin silinmesi başarısız oluyor. AMA, 'o' harfini sildi

İlginç olan şu benim için anlamlı olmayan aşağıdaki iki örnektir:

[root@host~]# echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-n]
opqrstuvwxyz1234567890
[root@host~]# echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-o]
abcdefghijklmnpqrstuvwxyz1234567890
[root@host~]#

(yine, son örnekte 'o' silinmiştir)

Burada neler olduğu hakkında bir fikri olan var mı? Kullandığım herhangi bir linux kutusunda üreyemiyorum.


5
Teğetsel olarak ilgili: traralıklar ek olmadan yazılmıştır [...]. Yani tr -d '[a-z]'öldürecek a-zve aynı zamanda karakterlerini [ve ]. tr -d a-zSadece harfleri öldürmek için kullanın a-z.
Satō Katsura

Yanıtlar:


24

ogeçerli dizinde bir dosyanız var

foo> ls
foo> echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
1234567890
foo> touch o
foo> echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
abcdefghijklmnpqrstuvwxyz1234567890

shell, [a-z]bir eşleşme bulunursa dizeyi genişletir .

Buna göre yol adı genişletmesi denir man bash

Yol Adı Genişletme
Kelime bölme işleminden sonra, -f seçeneği ayarlanmadığı sürece, bash her sözcüğü *,? Ve [karakterleri için tarar. ... (...)

bash genişleme yapacak.

[...] Ekteki karakterlerden herhangi biriyle eşleşir.


Sen kabuğun genişlemesini örneğin kullanarak kontrol edebilirsiniz @Chris echo: touch o ; echo tr -d [a-z]Bu veriyor:tr -d o
pabouk

8

Ne oluyor

Kabuk (bash) argümanı görür [a-z]. Bu , herhangi bir küçük harfle eşleşen bir joker desendir (bir glob ). Bu nedenle, kabuk bu kalıpla eşleşen bir dosya adı arar. Üç durum vardır:

  • Geçerli dizindeki hiçbir dosyanın tek bir küçük harfli adı yoktur. Sonra kabuk değişmeden joker desen bırakır ve trargümanları görür -dve [a-z]. Makinelerinizin çoğunda olan budur.
  • Geçerli dizindeki tek bir dosyanın adı tek küçük harftir. Daha sonra kabuk deseni bu dosya adına genişletir ve trargümanları -dve dosya adını görür . Bu sunucuda gerçekleşir ve mektubu sildiğini ogörebildiğimiz için eşleşen dosya çağrılır .tro
  • Geçerli dizindeki iki veya daha fazla dosya, tek küçük harfli bir ada sahiptir. Ardından kabuk, deseni eşleşen dosya adları listesine genişletir ve trüç veya daha fazla bağımsız değişken görür: -dve dosya adları. Yana trtek argüman sonra beklentiden -d, şikayet edecektir.

Ne yapmalıydın

Bir komutun argümanında özel karakterler varsa, bunlardan kaçmalısınız. Argümanı tek tırnak içine alın '…'(bu en basit yoldur, başkaları da vardır). Tek tırnak içinde, tek tırnak dışında tüm karakterler kendini gösterir. Argümanın içinde tek bir alıntı varsa, onu değiştirin'\'' .

tr -d '[a-z]'

Ancak bunun muhtemelen ne demek istediğinizi olmadığını unutmayın! Bu, trküçük harfleri ve köşeli parantezleri silmeyi söyler . Bu eşdeğerdir tr -d ']a-z[', tr '[]a-z'küçük harfleri silmek için, vb kullanımı

tr -d a-z

Argümanı trbir karakter kümesidir. Köşeli parantezleri, karakter kümesi olduğunu belirtmek için normal ifade veya joker karakter desenindeki bir karakter kümesinin etrafına koyarsınız. Ancak trher seferinde tek bir karakter üzerinde çalışır. Komut satırı argümanları parantez içine koyduğunuz şeydir .

Karakter sınıflarını belirtmek için köşeli parantezlere ihtiyacınız vardır . Normal bir ifadede, bir karakter sınıfını belirtmek için köşeli parantez içindeki köşeli parantezleri kullanırsınız, örneğin [[:lower:]]*herhangi bir sayıda küçük harfle [[:lower:]_]*eşleşir, herhangi bir sayıda küçük harfle ve alt çizgiyle eşleşir. Bağımsız değişkeninde tr, küme çevresindeki köşeli parantez olmadan gerekir, bu nedenle tr -d '[:lower:]'küçük harfleri tr -d '[:lower:]_'siler, küçük harfleri ve alt çizgileri siler.

Local Bazı yerlerde diğer karakterlerle eşleşebilir .


1
Solaris 10'da (ve diğer eski SysV tabanlı Unices'de) ihtiyacınız tr -d '[a-z]'olduğunu unutmayın /usr/bin/tr. İle /usr/xpg4/bin/tr, tr -d a-zçalışıyor ancak tr -d '[a-z]'silmez [ne de ].
Stéphane Chazelas

1
/usr/xpg4/bin/tr -d '[a-z]'Solaris 11'de silinmediği [veya ]düzeltildiği anlaşıldı
Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.