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