Zamiana niektórych znaków w ciągu na inny znak


279

Mam ciąg jak AxxBCyyyDEFzzLMN i chcę zastąpić wszystkie wystąpienia X , Y i Z z _ .

Jak mogę to osiągnąć?

Wiem, że echo "$string" | tr 'x' '_' | tr 'y' '_'to zadziała, ale chcę to zrobić za jednym razem, bez używania rur.


Czy chciałeś zastąpić dowolną sekwencję kolejnych x, y lub z jednym znakiem podkreślenia, czy chciałeś zastąpić każdy x, y lub z jednym znakiem podkreślenia? A co z sekwencjami mieszanymi AxyzB? Trzy podkreślenia czy jeden?
David Z

tr '[xyz]'zastąpi [i ]też. Argumentem powinna być po prostu lista znaków (chociaż zakresy jak a-zsą w porządku, aw niektórych implementacjach klasy znaków POSIX jak [:digit:]).
tripleee

Odpowiedzi:


329
echo "$string" | tr xyz _

zastąpi każde wystąpienie x, ylub zz _, dając A__BC___DEF__LMNw swoim przykładzie.

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

zastąpiłby powtarzające się wystąpienia x, yalbo zz jednym _, dając A_BC_DEF_LMNw swoim przykładzie.


19
Na Macu otrzymałem: sed: niedozwolona opcja - użycie r: sed skrypt [-Ealn] [rozszerzenie -i] [plik ...] sed [-Ealn] [rozszerzenie -i] [-e skrypt]. .. [-f plik_skryptu] ... [plik ...]
catanore

Mam ciąg znaków, który zawiera ,[]{}()~znaki. Chcę zastąpić go każdą uciekającą postacią specjalną, '\'jak mogę to zrobić za pomocą oneshota?
inckka

2
@halakala Mac jest dostarczany z nieco inną wersją sed. Zobacz to pytanie: unix.stackexchange.com/questions/13711/... Zamiast tego możesz zainstalować „gnu-sed” za pomocą menedżera pakietów Homebrew, a następnie użyć plikugsed binarnego:$ brew install gnu-sed wtedy$ gsed -r 's/[xyz]+/_/g'
John Kary

6
Na * BSD (a więc i OSX) sed -Ejest (w zasadzie) równoważny z sed -rwieloma dystrybucjami Linuksa. Jeśli używasz sed 's/[xyz][xyz]*/_/g', nie potrzebujesz tej opcji. Oczywiście jest to równoważne, tr -s xyz _więc nie ma sedtu potrzeby .
tripleee

@inckka Nie możesz tego użyć tr. sed 's/[][{}()~,]/\\&/g'ale tak naprawdę, zadaj nowe pytanie, jeśli masz pytanie uzupełniające (oczywiście możesz powrócić tutaj tutaj w celu odniesienia). Nawiasem mówiąc, ,i ~nie są regex metaznakami (choć ~zostaje rozszerzona na $HOMEniektórych pozycjach przez bash i niektórych innych powłok; nie shjednak).
tripleee

286

Korzystanie z rozszerzenia parametru Bash :

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

7
Zła zmiana
Aleksiej

1
@Alexey, mój przykład działa dla mnie (wydanie bash 4.3.11 (1)). Upewnij się, że używasz bash. Inne powłoki mogą nie działać (choć niektóre będą).
Matthew Flaschen

Dziękuję @MatthewFlaschen. Właśnie tego potrzebowałem, aby wykonać zamianę sed dla absolutnej ścieżki w skrypcie bash (zastąpienie / przez \ / tak sed to akceptuje).
Ryan G

1
@RyanG po co korzystać, sedjeśli bash ma wbudowane podstawienie?
MestreLion

@MestreLion To mogło się nie udać, ale musiałem zastąpić standardową nazwę zmiennej w wiązce plików bezwzględną ścieżką, dla której korzystałem z zamiany sed inplace. ale nie możesz mieć „/” bez zmiany znaczenia w poleceniu. Łączę operacje w bash. Czy nie byłby to najlepszy sposób manipulowania ciągiem w bash?
Ryan G

111

Ten link może być pomocny:

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

Ogólnie,

Aby zamienić pierwsze dopasowanie $ substring na $ replace:

${string/substring/replacement}

Aby zamienić wszystkie dopasowania $ substring na $ replace:

${string//substring/replacement}

EDYCJA: Zauważ, że dotyczy to zmiennej o nazwie $ string.


16
Zauważ, że działa to na zmiennej o nazwie „string”, a nie na literalnym ciągu.
mattdm

1
najbardziej pomocny, ponieważ zawiera referencje.
Os3

Najlepsze i najkrótsze rozwiązanie.
northtree

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

^ użyj ich tyle, ile potrzebujesz, i możesz wykonać własne szyfrowanie BASIC


5

Oto rozwiązanie z rozszerzaniem parametrów powłoki, które zastępuje wiele ciągłych wystąpień jednym _:

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

Zauważ, że wzorzec wymaga rozszerzonego dopasowywania wzorca, włączony przy pomocy+(pattern)

shopt -s extglob

Alternatywnie, z -sopcją („ściśnij”) tr:

$ tr -s xyz _ <<< "$var"
A_BC_DEF_LMN
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.