Rozwiązanie z samym sed
sed sam jest w stanie wyprodukować zarówno niezmodyfikowaną, jak i zmodyfikowaną linię:
$ echo "redis::staging::key" | sed 's/^/RENAME /; p; s/staging/development/g'
RENAME redis::staging::key
RENAME redis::development::key
Powyżej sed najpierw dodaje napis RENAME na początku linii. Następnie p
komenda mówi sedowi, aby wypisał linię w takiej formie, w jakiej jest w tym czasie (z wciąż w niej "staging"). Następne podstawienie wprowadza "rozwój", a następnie ta wersja jest również drukowana.
Aktualizacja: Załóżmy, że chcemy, aby wynik był w jednym wierszu:
$ echo "redis::staging::key" | sed 's/.*/RENAME & &/; s/staging/development/2'
RENAME redis::staging::key redis::development::key
Pierwsze s
powyższe polecenie dodaje RENAME na początek, a następnie podwaja linię. Drugi zastępuje drugie wystąpienie etapowania z rozwojem.
Dlaczego wersja xargs nie wykonała zamiany?
xargs -I {} echo "RENAME {} $(echo {} | sed 's/staging/development/g')"
Przed wykonaniem xargs, bash przetwarza łańcuchy. W szczególności widzi $(echo {} | sed 's/staging/development/g')
i wykonuje go („podstawianie polecenia”) i otrzymuje wynik {}
. Tak więc, kiedy xargs zostanie w końcu uruchomiony, zobaczy polecenie:
xargs -I {} echo "RENAME {} {}"
W konsekwencji s/staging/development/g
zastąpienie nigdy nie jest dokonywane.
Sprawianie, by xargs i powłoka działały razem we właściwej kolejności
Jest na to poprawka:
$ echo "redis::staging::key" | xargs -I {} sh -c 'echo RENAME {} $(echo {} | sed 's/staging/development/g')'
RENAME redis::staging::key redis::development::key
Powyższe umieszcza polecenia bash w pojedynczych cudzysłowach i przekazuje je jako argumenty do sh
. W ten sposób łańcuch nie jest przetwarzany przez powłokę, dopóki xargs nie wykona podstawień.