Заміна деяких символів у рядку іншим символом


279

У мене є такий рядок, як AxxBCyyDEFzzLMN, і я хочу замінити всі випадки x , y і z на _ .

Як я можу цього досягти?

Я знаю, що echo "$string" | tr 'x' '_' | tr 'y' '_'це спрацювало б, але я хочу це зробити за один раз, не використовуючи труби.


Чи хотіли ви замінити будь-яку послідовність послідовних x, y або z на одну підкреслення, або ви хотіли замінити кожен x, y або z одним підкресленням? А як щодо змішаних послідовностей, як AxyzB? Три підкреслення або одна?
David Z

tr '[xyz]'замінить [і ]теж. Аргументом повинен бути просто список символів (хоча діапазони на зразок a-zнормальні, а в деяких реалізаціях - клас класів символів POSIX [:digit:]).
tripleee

Відповіді:


329
echo "$string" | tr xyz _

замінить кожне входження x, yабо zз _, що дає A__BC___DEF__LMNв вашому прикладі.

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

замінить повторювані входження x, yабо zз одним _, даючи A_BC_DEF_LMNв вашому прикладі.


19
На Mac я отримав наступне: sed: незаконний варіант - r використання: sed script [-Ealn] [-i розширення] [файл ...] sed [-Ealn] [-i розширення] [-e script]. .. [-f script_file] ... [file ...]
катанор

У мене є рядок, що містить ,[]{}()~символи. Я хочу замінити його на кожен спеціальний персонаж, що втік, на '\'те, як я міг зробити це за допомогою onehot?
inckka

2
@halakala Mac постачається з дещо іншою версією sed. Дивіться це запитання: unix.stackexchange.com/questions/13711/… Натомість ви можете встановити "gnu-sed" за допомогою менеджера пакунків Homebrew, а потім скористатися gsedдвійковим файлом: $ brew install gnu-sedтоді$ gsed -r 's/[xyz]+/_/g'
Джон Карі

6
У режимі * BSD (і, таким чином, OSX) sed -Eє (в основному) еквівалентним у sed -rбагатьох дистрибутивах Linux, якщо ви користуєтесь, sed 's/[xyz][xyz]*/_/g'вам не потрібна опція. Звичайно, це рівнозначно, tr -s xyz _тому тут немає реальної потреби sed.
tripleee

@inckka Ви не можете використовувати trдля цього. sed 's/[][{}()~,]/\\&/g'але насправді, задайте нове запитання, якщо у вас є додаткове запитання (звичайно, сміливо посилайтесь тут для довідки). До речі, ,і ~нерегулярно вираження метасимволов (хоча ~отримує розширені до $HOMEв деяких положеннях Bash і деяких інших оболонках, а НЕ shоднак).
tripleee

286

Використання розширення параметра Bash :

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

7
Погана заміна
Олексій

1
@ Алекс, мій приклад працює для мене (баш 4.3.11 (1) -випуск). Переконайтеся, що ви використовуєте bash. Інші снаряди можуть не працювати (хоча деякі будуть).
Меттью Флашен

Дякую @MatthewFlaschen Це саме те, що мені потрібно було зробити заміну sed для абсолютного шляху в скрипті bash (заміна / / \ / тому sed приймає це).
Райан Г

1
@RyanG навіщо використовувати, sedякщо bash має вбудовану заміну?
MestreLion

@MestreLion Це, можливо, вийшло неправильно, але мені потрібно було замінити стандартне ім'я змінної у купі файлів на абсолютний шлях, для якого я використовував sed inplace заміну. але ви не можете мати "/", не уникаючи цього в команді. Я нанизував операції разом у баш. Хіба це не буде найкращим способом маніпулювання струною в баші?
Ryan G

111

Це посилання може бути корисним:

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

В загальному,

Щоб замінити перший матч $ підрядка на $ заміну:

${string/substring/replacement}

Щоб замінити всі збіги $ substring на $ заміну:

${string//substring/replacement}

EDIT: Зауважте, що це стосується змінної з назвою $ string.


16
Зауважте, що це працює на змінній з назвою "string", а не на прямому рядку.
mattdm

1
найбільш корисна, оскільки містить посилання.
Ос3

Найкраще і найкоротше рішення.
northtree

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

^ використовуйте стільки, скільки вам потрібно, і ви можете зробити власне БАЗОВЕ шифрування


5

Ось рішення з розширенням параметрів оболонки, яке замінює декілька суміжних подій на один _:

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

Зауважте, що для візерунка потрібна розширена відповідність шаблону, увімкнена за допомогою+(pattern)

shopt -s extglob

Крім того, з -sопцією ("стискати") tr:

$ tr -s xyz _ <<< "$var"
A_BC_DEF_LMN
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.