A sed használatával megtalálja és kicserélje a bonyolult karakterláncot (előnyösen regexszel)

A következő tartalmú fájlom van:

<username><![CDATA[name]]></username> <password><![CDATA[password]]></password> <dbname><![CDATA[name]]></dbname> 

és készítenem kell egy szkriptet, amely az első sor” nevét “” valamire “, a második sorában a” jelszót “” valamire “és a” nevet ” a harmadik sor a “valami más” kifejezésre. “Nem támaszkodhatok ezek sorrendjére a fájlban, így nem” egyszerűen helyettesíthetem a “név” első előfordulását “valamivel”, a “név” második előfordulását pedig “valami mással”. Valójában meg kell keresnem a környező karakterláncokat, hogy megbizonyosodjak arról, hogy a megfelelő dolgot megtalálom és kicserélem.

Eddig ezt a parancsot próbáltam megtalálni és kicserélni az első “név” előfordulást:

sed -i "s/<username><![CDATA[name]]><\/username>/something/g" file.xml 

ez azonban nem működik, ezért azt gondolom, hogy ezeknek a karaktereknek némelyikének esetleg el kell menekülnie, stb.

Ideális esetben én ” Szeretem, ha a regex használatával csak a két “felhasználónév” előfordulást illesztjük össze, és csak a “nevet” cseréljük ki. Valami ilyesmi, de a következővel: sed:

<username>.+?(name).+?</username> 

és a zárójelben lévő tartalmat cserélje le valamire.

Ez lehetséges?

Megjegyzések

  • Csak vegye figyelembe, hogy nagyjából minden regexp alapú megoldás, kivéve, ha rendkívül mesterkélt, megkockáztatja bármikor megtörve, ha a beviteli formátum változik. A regexps nem megfelelő választás az XML, SGML vagy származékok kezelésére (ez nekem látszik).
  • Jóváhagyva! Fontolja meg például az XQuery használatát: w3schools.com/xquery/default.asp . Ez a W3C szabvány az XML-tartalom lekérésére és kezelésére.

Válasz

sed -i -E "s/(<username>.+)name(.+<\/username>)/\1something\2/" file.xml 

Azt hiszem, ez az, amit keres.

Magyarázat:

  • az első részben zárójelben olyan csoportok (tulajdonképpen karakterláncok) találhatók, amelyek a második részben újra felhasználható
  • \1, \2 stb., a második részben hivatkozások a Az első részben elfoglalt i-edik csoport (a számozás 1-gyel kezdődik)
  • -E lehetővé teszi a kiterjesztett reguláris kifejezéseket (szükséges a + és csoportosítás).

Megjegyzések

  • +1 az -E opcióhoz
  • hátrahagy egy biztonsági másolatot, a következő névvel: (original name) + "-E".
  • OSX-en ‘ sed: 1: ” s / (< felhasználónév >. +) név (. + … “: \ 1 nem a RE ‘. A kérdés pontos példáját fájlba illesztettem. akkor futtattam a parancsot ebből a válaszból arra a fájlra. Lehet, hogy az OSX más szintaxissal rendelkezik?
  • A sed gnu verziója támogatja a ” -E ” paramétert, de nem hivatalos. ‘ nem is említik a kézikönyvben. Ha a kiterjesztett regexet akarja használni, akkor ehelyett a ” -r ” paramétert kell használnia.
  • @ deweydb ennek a válasznak megfelelően használja a \( és a \) ( és ) helyett.

Válasz

sed -e "/username/s/CDATA\[name\]/CDATA\[something\]/" \ -e "/password/s/CDATA\[password\]/CDATA\[somethingelse\]/" \ -e "/dbname/s/CDATA\[name\]/CDATA\[somethingdifferent\]/" file.txt 

A /username/ a s előtt mondja a sed hogy csak a “felhasználónév” karakterláncot tartalmazó sorokon dolgozzon.

Megjegyzések

  • Elegáns, hatékony és tökéletesen illeszkedik a tokhoz. +1

Válasz

Ha a sed nem nehéz követelmény, inkább használjon dedikált eszközt.

Ha a fájlod érvényes XML (nem csak az a 3 XML kinézetű címke), akkor használhat XMLStarlet :

xml ed -P -O -L \ -u "//username/text()" -v "something" \ -u "//password/text()" -v "somethingelse" \ -u "//dbname/text()" -v "somethingdifferent" file.xml 

A fentiek olyan helyzetekben is működnek, amelyeket reguláris kifejezésekkel nehéz megoldani:

  • Helyettesítheti a címkék értékeit anélkül, hogy megadná az aktuális értékeket.
  • Akkor is helyettesítheti az értékeket, ha éppen nincsenek megadva, és nincsenek bezárva a CDATA-ba.
  • Még akkor is helyettesítheti az értékeket a címkék attribútumokkal rendelkeznek.
  • Könnyen helyettesítheti a címkék csak előfordulásait, ha több ugyanazzal a névvel rendelkezik.
  • Formázhatja a módosított XML-t behúzással.

A fentiek rövid bemutatása:

bash-4.2$ cat file.xml <sith> <master> <username><![CDATA[name]]></username> </master> <apprentice> <username><![CDATA[name]]></username> <password>password</password> <dbname foo="bar"><![CDATA[name]]></dbname> </apprentice> </sith> bash-4.2$ xml ed -O -u "//apprentice/username/text()" -v "something" -u "//password/text()" -v "somethingelse" -u "//dbname/text()" -v "somethingdifferent" file.xml <sith> <master> <username><![CDATA[name]]></username> </master> <apprentice> <username><![CDATA[something]]></username> <password>somethingelse</password> <dbname foo="bar"><![CDATA[somethingdifferent]]></dbname> </apprentice> </sith> 

Válasz

$ sed -e "1s/name/something/2" \ -e "3s/name/somethingdifferent/2" \ -e "s/password/somethingelse/2" sample.xml 

Egyszerűen használhatja a címeket a s az “s” előtti számban, amely a sorszámot jelöli.

A végén lévő szám is azt mondja, hogy sed írja a második mérkőzést az első helyett. mérkőzés.

Válasz

Idéznie kell a \[.*^$/ t a s parancs és \&/ a pótalkatrészben, plusz új sorok. A reguláris kifejezés egy alapszabályos kifejezés , és emellett meg kell idéznie a s parancs elválasztóját is.

Választhat egy másik elválasztót, hogy ne kelljen idéznie a / szót. Ehelyett ezt a karaktert kell idéznie, de általában az elválasztó megváltoztatásának lényege, hogy olyat válasszon, amely nem fordul elő sem a cserélendő, sem a helyettesítő szövegben.

sed -e "s~<username><!\[CDATA\[name\]\]></username>~<username><![CDATA[something]]></username>~" 

A csoportok használatával elkerülhető a részek ismétlése a helyettesítő szövegben, és ezeken a részeken variáció áll rendelkezésre.

sed -e "s~\(<username><!\[[A-Z]*\[\)name\(\]\]></username>\)~\1something\2~" sed -e "s~\(<username>.*[^A-Za-z]\[\)name\([^A-Za-z].*</username>\)~\1something\2~" 

Válasz

A “név” szó helyettesítésére a “valami” szóra használja a következőt:

sed "s/\(<username><\!\[[A-Z]*\[\)name\]/\1something/g" file.xml 

Ez helyettesíti a megadott szó összes előfordulását.

Eddig az összes szabványos kimenetre lett kiadva, használhatja:

sed "s/\(<username><\!\[[A-Z]*\[\)name\]/\1something/g" file.xml > anotherfile.xml 

a módosítások mentéséhez egy másik fájlba.

Válasz

Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... -r, --regexp-extended use extended regular expressions in the script. 

tehát egy tulajdonságfájl értékének helyettesítésére

sed -i -r "s/MAIL\=(.+)/MAIL\[email protected]/" etc/service.properties 

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük