Mam plik o następującej treści:
<username><![CDATA[name]]></username>
<password><![CDATA[password]]></password>
<dbname><![CDATA[name]]></dbname>
i muszę stworzyć skrypt, który zmieni „imię” w pierwszym wierszu na „coś”, „hasło” w drugim wierszu na „coś”, a „imię” w trzecim wierszu na „coś innego”. Nie mogę polegać na kolejności występowania w pliku, więc nie mogę po prostu zastąpić pierwszego wystąpienia „nazwy” słowem „coś”, a drugiego wystąpienia „nazwy” słowem „coś innego”. Właściwie muszę wyszukać otaczające ciągi, aby upewnić się, że znajduję i zastępuję poprawną rzecz.
Do tej pory próbowałem tego polecenia, aby znaleźć i zastąpić pierwsze wystąpienie „name”:
sed -i "s/<username><![CDATA[name]]><\/username>/something/g" file.xml
jednak to nie działa, więc myślę, że niektóre z tych postaci mogą wymagać ucieczki itp.
Idealnie, chciałbym móc użyć wyrażenia regularnego, aby po prostu dopasować dwa wystąpienia „nazwy użytkownika” i zastąpić tylko „imię”. Coś takiego, ale z sed
:
<username>.+?(name).+?</username>
i zamień zawartość w nawiasach na „coś”.
czy to możliwe?
źródło
Odpowiedzi:
Myślę, że tego właśnie szukasz.
Wyjaśnienie:
\1
,\2
itp. w drugiej części są odniesieniami do i-tej grupy uchwyconej w pierwszej części (numeracja zaczyna się od 1)-E
włącza rozszerzone wyrażenia regularne (potrzebne+
i grupujące).źródło
(original name) + "-E"
.\(
i\)
zamiast(
i)
./username/
Przeds
nakazuje sed tylko pracy na liniach zawierających ciąg „nazwę użytkownika”.źródło
Jeśli
sed
nie jest to trudne wymaganie, lepiej użyć dedykowanego narzędzia.Jeśli plik ma poprawny kod XML (nie tylko te 3 znaczniki wyglądające na XML), możesz użyć XMLStarlet :
Powyższe będzie również działać w sytuacjach, które trudno byłoby rozwiązać za pomocą wyrażeń regularnych:
Krótka prezentacja powyższych:
źródło
Musisz cytować
\[.*^$/
w części wyrażenia regularnegos
polecenia oraz\&/
w części zastępczej, a także nowe wiersze. Wyrażenie regularne jest podstawowym wyrażeniem regularnym , a ponadto musisz podać cudzysłów dlas
polecenia.Możesz wybrać inny separator, aby uniknąć konieczności cytowania
/
. Zamiast tego musisz zacytować ten znak, ale zwykle celem zmiany separatora jest wybranie takiego, który nie występuje ani w tekście, który ma zostać zastąpiony, ani w tekście zastępującym.Możesz użyć grup, aby uniknąć powtarzania niektórych części w tekście zamiennym i dostosować warianty tych części.
źródło
Możesz po prostu użyć adresów jak w numerze poprzedzającym „s”, który wskazuje numer linii.
Również liczba na końcu mówi
sed
o zastąpieniu drugiego dopasowania zamiast pierwszego.źródło
Aby zastąpić słowo „nazwa” słowem „coś”, użyj:
To zastąpi wszystkie wystąpienia określonego słowa.
Do tej pory wszystko jest wyprowadzane na standardowe wyjście, możesz użyć:
aby zapisać zmiany w innym pliku.
źródło
aby zastąpić wartość w pliku właściwości
źródło