@ruakh jak napisać to oświadczenie z warunkiem lub. Tylko jeśli chcę zastąpić Suzi lub Marry nowym ciągiem.
Priyatham51
3
@ Priyatham51: Nie ma do tego wbudowanej funkcji. Wystarczy wymienić jeden, a potem drugi.
ruakh
4
@Bu: Nie, ponieważ \nw tym kontekście reprezentowałby siebie, a nie nowy wiersz. Nie mam Bash poręczny prawo teraz do testu, ale powinieneś być w stanie napisać coś podobnego $STRING="${STRING/$'\n'/<br />}". (Chociaż prawdopodobnie chcesz STRING//- zamień wszystko - zamiast tylko STRING/.)
ruakh
25
Żeby było jasne, ponieważ trochę mnie to pomieszało, pierwsza część musi być zmiennym odniesieniem. Nie można tego zrobić echo ${my string foo/foo/bar}. Potrzebujeszinput="my string foo"; echo ${input/foo/bar}
Henrik N
2
@mgutt: Ta odpowiedź prowadzi do odpowiedniej dokumentacji. Dokumentacja nie jest doskonała - na przykład, zamiast //bezpośrednio wspomnieć , wspomina, co się dzieje „Jeśli wzorzec zaczyna się od /„ ”(co nie jest nawet dokładne, ponieważ reszta tego zdania zakłada, że dodatkowe /nie jest tak naprawdę częścią wzór) - ale nie znam lepszego źródła.
ruakh
208
Można to zrobić całkowicie za pomocą manipulacji ciągiem bash:
first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}
To zastąpi tylko pierwsze wystąpienie; aby zamienić je wszystkie, podwój pierwszy ukośnik:
first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}# first is now "Sara, Sara, Sara"
Po co mieć odpowiedź, która powiela zaakceptowaną, zamiast edytować zaakceptowaną z opcją globalnej zamiany? I dodając, że wyrażenia regularne są obsługiwane, podczas gdy w tym. I wyjaśnienie, co słychać w „złym zastąpieniu”. Masz wystarczającą liczbę punktów, @Kevin :)
Dan Dascalescu
6
Wygląda na to, że oboje odpowiedzieli dokładnie w tej samej minucie: O
Jamie Hutber
76
W przypadku Dasha wszystkie poprzednie posty nie działają
Rozwiązaniem shzgodnym z POSIX jest:
result=$(echo "$firstString"| sed "s/Suzi/$secondString/")
Mam to: $ echo $ (echo $ firstString | sed 's / Suzi / $ secondString / g') Uwielbiam $ secondString i Marry
Qstnr_La
2
@Qstnr_La używaj podwójnych cudzysłowów do podstawiania zmiennych:result=$(echo $firstString | sed "s/Suzi/$secondString/g")
emc
1
Plus 1 za pokazanie, jak wyprowadzać dane do zmiennej. Dzięki!
Szef kuchni Faraon
2
Naprawiłem pojedyncze cytaty, a także dodałem brakujące cytaty wokół echoargumentu. Zwodniczo działa bez cytowania przy użyciu prostych ciągów, ale łatwo psuje dowolny nietrywialny ciąg wejściowy (nieregularne odstępy, metaznaki powłoki itp.).
tripleee
W sh (AWS Codebuild / Ubuntu sh) stwierdziłem, że potrzebuję jednego ukośnika na końcu, a nie podwójnego. Zamierzam edytować komentarz, ponieważ powyższe komentarze pokazują również pojedynczy ukośnik.
Tak naprawdę nie potrzebujesz do tego Sed; Bash obsługuje ten rodzaj wymiany natywnie.
ruakh
12
Myślę, że jest to oznaczone jako „bash”, ale przyszło tutaj, ponieważ potrzebowałem czegoś prostego dla innej powłoki. To miła, zwięzła alternatywa dla tego, co wiki.ubuntu.com/... sprawiło, że wyglądało na to, że potrzebuję.
natevw
3
Działa to doskonale dla ash / dash lub dowolnego innego POSIX sh.
Ta odpowiedź zatrzymał mnie od korzystania sedz pwdpoleceniem, aby uniknąć definiowania nowej zmiennej za każdym razem moje własne $PS1przejazdy. Czy Bash zapewnia bardziej ogólny sposób niż zmienne magiczne wykorzystanie wyjścia polecenia do zamiany łańcucha? Jeśli chodzi o twój kod, musiałem uciec, ~aby Bash nie rozwinął go do $ HOME. Co również robi #twoje polecenie?
Mark Haferkamp
1
@MarkHaferkamp Zobacz to z linku „zalecane dalsze czytanie”. O „ucieczce ~”: zauważ, jak cytowałem różne rzeczy. Pamiętaj, aby zawsze cytować różne rzeczy! I to nie działa tylko w przypadku zmiennych magicznych: każda zmienna jest zdolna do podstawiania, uzyskiwania długości łańcucha i więcej w ramach bash. Gratulujemy $PS1postu: możesz być także zainteresowany, $PROMPT_COMMANDjeśli czujesz się lepiej w innym języku programowania i chcesz zakodować skompilowane zapytanie.
Camilo Martin
Link „dalsze czytanie” wyjaśnia „#”. Na Bash 4.3.30, echo "${PWD/#$HOME/~}"nie zastąpią mi $HOMEsię ~. Wymiana ~z \~lub '~'prace. Każda z nich działa na Bash 4.2.53 w innej dystrybucji. Czy możesz zaktualizować swój post, aby zacytować lub uciec przed ~lepszą kompatybilnością? Moje pytanie „magiczne zmienne” miałem na myśli: czy mogę użyć podstawienia zmiennej Basha, np. Na wyjściu unamebez zapisywania go jako zmiennej? Jeśli chodzi o mój osobisty $PROMPT_COMMAND, to skomplikowane .
Ponieważ nie mogę dodać komentarza. @ruaka Aby uczynić przykład bardziej czytelnym, napisz go w ten sposób
full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}
Dopóki nie przyszedłem do twojego przykładu, zrozumiałem kolejność na odwrót. Pomogło to wyjaśnić, co się dzieje
raghav710,
5
Czysta POSIX metoda powłoki, które w odróżnieniu od Roman Kazanovskyi „s sedopartym odpowiedź potrzebuje żadnych zewnętrznych narzędzi, zaledwie ojczystym skorupy za ekspansje parametrów . Zauważ, że długie nazwy plików są zminimalizowane, więc kod lepiej pasuje do jednej linii:
f="I love Suzi and Marry"
s=Sara
t=Suzi["${f%$t*}"!="$f"]&& f="${f%$t*}$s${f#*$t}"
echo "$f"
Wynik:
I love Sara and Marry
Jak to działa:
Usuń najmniejszy wzór sufiksu. "${f%$t*}"zwraca „ I love”, jeśli sufiks $t„ Suzi*” jest w $f„ ”. I loveSuzi and Marry
Ale jeśli t=Zelda, to "${f%$t*}"nic nie usuwa i zwraca cały ciąg „ I love Suzi and Marry”.
Służy do testowania, czy $tjest w, $fz [ "${f%$t*}" != "$f" ]którym ma wartość true, jeśli $fciąg zawiera „ Suzi*”, a fałsz, jeśli nie.
Jeśli test zwróci wartość true , skonstruuj żądany ciąg znaków, używając opcji Usuń najmniejszy wzorzec sufiksu${f%$t*} „ I love” i Usuń najmniejszy wzorzec prefiksu${f#*$t} „ and Marry”, z drugim ciągiem $s„ Sara” pomiędzy nimi.
Odpowiedzi:
Aby zastąpić pierwsze wystąpienie wzorca danym ciągiem, użyj :
${parameter/pattern/string}
Aby zastąpić wszystkie wystąpienia, użyj :
${parameter//pattern/string}
(Jest to opisane w podręczniku atakujących odniesienia , §3.5.3 „Shell parametrów Expansion” ).
Zauważ, że ta funkcja nie jest określona przez POSIX - jest to rozszerzenie Bash - więc nie wszystkie powłoki Unix ją implementują. Aby zapoznać się z odpowiednią dokumentacją POSIX, zobacz Podstawową specyfikację standardu technicznego Open Group, wydanie 7 , tom Shell & Utilities , § 2.6.6 „Rozszerzanie parametrów” .
źródło
\n
w tym kontekście reprezentowałby siebie, a nie nowy wiersz. Nie mam Bash poręczny prawo teraz do testu, ale powinieneś być w stanie napisać coś podobnego$STRING="${STRING/$'\n'/<br />}"
. (Chociaż prawdopodobnie chceszSTRING//
- zamień wszystko - zamiast tylkoSTRING/
.)echo ${my string foo/foo/bar}
. Potrzebujeszinput="my string foo"; echo ${input/foo/bar}
//
bezpośrednio wspomnieć , wspomina, co się dzieje „Jeśli wzorzec zaczyna się od/
„ ”(co nie jest nawet dokładne, ponieważ reszta tego zdania zakłada, że dodatkowe/
nie jest tak naprawdę częścią wzór) - ale nie znam lepszego źródła.Można to zrobić całkowicie za pomocą manipulacji ciągiem bash:
To zastąpi tylko pierwsze wystąpienie; aby zamienić je wszystkie, podwój pierwszy ukośnik:
źródło
W przypadku Dasha wszystkie poprzednie posty nie działają
Rozwiązaniem
sh
zgodnym z POSIX jest:źródło
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echo
argumentu. Zwodniczo działa bez cytowania przy użyciu prostych ciągów, ale łatwo psuje dowolny nietrywialny ciąg wejściowy (nieregularne odstępy, metaznaki powłoki itp.).Spróbuj tego:
źródło
Lepiej jest używać bash, niż
sed
jeśli łańcuchy zawierają znaki RegExp.Jest przenośny dla systemu Windows i działa z co najmniej tak starym jak Bash 3.1.
Aby pokazać, że nie musisz się zbytnio przejmować ucieczką, obróćmy to:
Zaangażowany w to:
Ale tylko jeśli
/home/name
jest na początku. Nie potrzebujemysed
!Biorąc pod uwagę, że bash daje nam magiczne zmienne
$PWD
i$HOME
możemy:EDYCJA: Dzięki za Mark Haferkamp w komentarzach do notatki na temat cytowania / ucieczki
~
. *Zauważ, że zmienna
$HOME
zawiera ukośniki, ale to niczego nie zepsuło.Dalsza lektura: Przewodnik po zaawansowanych skryptach bashowych .
Jeśli używanie
sed
jest koniecznością, pamiętaj o ucieczce każdej postaci .źródło
sed
zpwd
poleceniem, aby uniknąć definiowania nowej zmiennej za każdym razem moje własne$PS1
przejazdy. Czy Bash zapewnia bardziej ogólny sposób niż zmienne magiczne wykorzystanie wyjścia polecenia do zamiany łańcucha? Jeśli chodzi o twój kod, musiałem uciec,~
aby Bash nie rozwinął go do $ HOME. Co również robi#
twoje polecenie?~
”: zauważ, jak cytowałem różne rzeczy. Pamiętaj, aby zawsze cytować różne rzeczy! I to nie działa tylko w przypadku zmiennych magicznych: każda zmienna jest zdolna do podstawiania, uzyskiwania długości łańcucha i więcej w ramach bash. Gratulujemy$PS1
postu: możesz być także zainteresowany,$PROMPT_COMMAND
jeśli czujesz się lepiej w innym języku programowania i chcesz zakodować skompilowane zapytanie.echo "${PWD/#$HOME/~}"
nie zastąpią mi$HOME
się~
. Wymiana~
z\~
lub'~'
prace. Każda z nich działa na Bash 4.2.53 w innej dystrybucji. Czy możesz zaktualizować swój post, aby zacytować lub uciec przed~
lepszą kompatybilnością? Moje pytanie „magiczne zmienne” miałem na myśli: czy mogę użyć podstawienia zmiennej Basha, np. Na wyjściuuname
bez zapisywania go jako zmiennej? Jeśli chodzi o mój osobisty$PROMPT_COMMAND
, to skomplikowane .Jeśli jutro zdecydujesz, że nie kochasz Marry, ona również może zostać zastąpiona:
Musi być 50 sposobów na opuszczenie kochanka.
źródło
Ponieważ nie mogę dodać komentarza. @ruaka Aby uczynić przykład bardziej czytelnym, napisz go w ten sposób
źródło
Czysta POSIX metoda powłoki, które w odróżnieniu od Roman Kazanovskyi „s
sed
opartym odpowiedź potrzebuje żadnych zewnętrznych narzędzi, zaledwie ojczystym skorupy za ekspansje parametrów . Zauważ, że długie nazwy plików są zminimalizowane, więc kod lepiej pasuje do jednej linii:Wynik:
Jak to działa:
Usuń najmniejszy wzór sufiksu.
"${f%$t*}"
zwraca „I love
”, jeśli sufiks$t
„Suzi*
” jest w$f
„ ”.I love
Suzi and Marry
Ale jeśli
t=Zelda
, to"${f%$t*}"
nic nie usuwa i zwraca cały ciąg „I love Suzi and Marry
”.Służy do testowania, czy
$t
jest w,$f
z[ "${f%$t*}" != "$f" ]
którym ma wartość true, jeśli$f
ciąg zawiera „Suzi*
”, a fałsz, jeśli nie.Jeśli test zwróci wartość true , skonstruuj żądany ciąg znaków, używając opcji Usuń najmniejszy wzorzec sufiksu
${f%$t*}
„I love
” i Usuń najmniejszy wzorzec prefiksu${f#*$t}
„and Marry
”, z drugim ciągiem$s
„Sara
” pomiędzy nimi.źródło
Wiem, że to stare, ale ponieważ nikt nie wspomniał o używaniu awk:
źródło
źródło