Bir dizedeki bazı karakterleri başka bir karakterle değiştirme


279

AxxBCyyyDEFzzLMN gibi bir dize var ve x , y ve z tüm oluşumları _ ile değiştirmek istiyorum .

Bunu nasıl başarabilirim?

Bunun echo "$string" | tr 'x' '_' | tr 'y' '_'işe yarayacağını biliyorum , ama bunu bir seferde boru kullanmadan yapmak istiyorum.


Herhangi bir ardışık x, y veya z dizisini bir alt çizgiyle değiştirmek mi istediniz , yoksa her x, y veya z'yi bir alt çizgiyle değiştirmek mi istediniz? Ayrıca, karışık dizilere ne dersiniz AxyzB? Üç alt çizgi mi yoksa bir alt çizgi mi?
David Z

tr '[xyz]'yerini alacak [ve ]. Argüman sadece karakterlerin bir listesi olmalıdır (ancak aralıklar a-ztamamdır ve bazı uygulamalarda POSIX karakter sınıfları gibi [:digit:]).
tripleee

Yanıtlar:


329
echo "$string" | tr xyz _

yapılan her çağrının yerini alacak x, yya zile _vererek A__BC___DEF__LMNsizin örnekte.

echo "$string" | sed -r 's/[xyz]+/_/g'

tekrarlayan tekrarlarını değiştirmek istiyorum x, yya ztek bir _vererek A_BC_DEF_LMNsizin örnekte.


19
Mac'te aşağıdakileri aldım: sed: illegal seçenek - r kullanımı: sed komut dosyası [-Ealn] [-i uzantı] [dosya ...] sed [-Ealn] [-i uzantı] [-e komut dosyası]. .. [-f script_file] ... [dosya ...]
catanore

,[]{}()~Karakter içeren bir dize var . Bunu, kaçan her özel karakterle değiştirmek istiyorum. Bunu '\'oneshot tarafından nasıl yapabilirim?
inckka

2
@halakala Mac, sed'in biraz farklı bir sürümüyle birlikte gelir. Bu soruya bakın: unix.stackexchange.com/questions/13711/… Bunun yerine "gnu-sed" i Homebrew paket yöneticisi ile kurabilir ve sonra gsedikili dosyayı kullanabilirsiniz : $ brew install gnu-sedo zaman$ gsed -r 's/[xyz]+/_/g'
John Kary

6
On * BSD (ve dolayısıyla OSX), sed -E(temelde) sed -rbirçok Linux dağıtımına eşdeğerdir , Eğer kullanıyorsanız sed 's/[xyz][xyz]*/_/g', seçeneğe ihtiyacınız yoktur. Tabii ki, bu eşdeğerdir, bu tr -s xyz _yüzden sedburada gerçek bir ihtiyaç yoktur .
tripleee

@inckka Bunun triçin kullanamazsın . sed 's/[][{}()~,]/\\&/g'ancak gerçekten, bir takip sorunuz varsa yeni bir soru sorun (elbette referans için buraya bağlantı kurmaktan çekinmeyin). Bu arada ,ve ~regex metakarakterler değildir (ancak bazı pozisyonlarda Bash ve diğer kabuklar tarafından ~genişletilir $HOME; shancak değil ).
tripleee

286

Bash Parametre Genişletmesini Kullanma :

orig="AxxBCyyyDEFzzLMN"
mod=${orig//[xyz]/_}

7
Kötü değişiklik
Alexey

1
@Alexey, örneğim benim için çalışıyor (bash 4.3.11 (1) -çalışma). Kullandığınızdan emin olun bash. Diğer mermiler çalışmayabilir (bazıları da işe yarayacaktır).
Matthew Flaschen

Teşekkürler @ MattFlaschen. Bu tam olarak bir bash komut dosyasında mutlak bir yol için bir sed yerine yapmak için gerekli (/ / / sed yerine kabul eder).
Ryan G

1
@RyanG neden sedbash yerleşik ikamesi kullanıyorsunuz?
MestreLion

@MestreLion Bu yanlış gelmiş olabilir, ama ben bir dizi dosyada standart değişken adını mutlak bir yol ile değiştirmek gerekiyordu, bunun için sed inplace değiştirme kullanıyordum. ancak komuttan kaçmadan "/" karakterine sahip olamazsınız. Operasyonları bash'ta birleştiriyordum. Bu, bash dizesini değiştirmenin en iyi yolu olmaz mıydı?
Ryan G

111

Bu bağlantıyı faydalı bulabilirsiniz:

http://tldp.org/LDP/abs/html/string-manipulation.html

Genel olarak,

$ Substring'in ilk eşleşmesini $ replacement ile değiştirmek için:

${string/substring/replacement}

$ Substring'in tüm eşleşmelerini $ replacement ile değiştirmek için:

${string//substring/replacement}

EDIT: Bunun $ string adlı bir değişken için geçerli olduğunu unutmayın.


16
Bunun değişmez dizede değil, "string" adlı bir değişken üzerinde çalıştığını unutmayın .
mattdm

1
referans içerdiğinden en yararlısıdır.
Os3

En iyi ve en kısa çözüm.
northtree

8
read filename ;
sed -i 's/letter/newletter/g' "$filename" #letter

^ bunlardan istediğiniz kadar yararlanın ve kendi BASIC şifrelemenizi yapabilirsiniz


5

Birden fazla bitişik olayı tek bir taneyle değiştiren shell parametre genişlemesine sahip bir çözüm _:

$ var=AxxBCyyyDEFzzLMN
$ echo "${var//+([xyz])/_}"
A_BC_DEF_LMN

Desenin , açıkken genişletilmiş desen eşlemesi gerektirdiğine dikkat edin.+(pattern)

shopt -s extglob

Alternatif olarak, -s("sıkıştır") seçeneği ile tr:

$ tr -s xyz _ <<< "$var"
A_BC_DEF_LMN
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.