[MEGOLDVA] sed parancs használata változóval, ami tartalmaz / jelet

Fórumok

Sziasztok. Abba a problémába futottam bele, hogy egy fileból ki kellene törölnöm minden olyan sort, ami egy megadott stringet tartalmaz. A probléma az, hogy a megadott string valójában valamilyen útvonal, vagyis tartalmaz / jelet.

Azt olvastam; hogy ilyenkor a sed parancsot át kell alakítani, hogy az elválasztójel | legyen. pl:

sed -i "s|$f|valami|g" file

Viszont ez a megoldás nem működik, ha sor törléséről van szó:

sed -i "|$f|d" file

Ekkor expression errort és unknown | -t ír ki.

Most ideiglenesen úgy oldottam meg, hogy elöszőr kicserélem egy olyan karakterláncra, ami sose fordulna elő, és utána azt a karakterláncot törlöm, tehát:

sed -i "s|$f|valami85473wert|g" file
sed -i '/valami85473wert/d' file

Csak azért ez nem egy túl elegáns megoldás, még ha így logikus és műküdik is. Van arra megoldás, hogy a sed-nél ha sort törlök, akkor a változóban szereplő / jel ne zavarja meg?

Hozzászólások

Bashban lehet ezzel próbálkozni:

sed "s/${f//\//\\\/}/valami/g" ...

(escapeled a $f-et)
 

A sed-nel a /.../ a range, amin az utana megadott parancsot vegrehajtja, mig az  's' a replace parancs, aminel parameterezheto az elvalaszto karakter. sed "\A${f}A d" ?

sed "\A${f}A d"  file nem működik.

Amúgy értem, hogy a / közötti a range alapesetben, de megadott sorok törléséhez is pont ugyanígy kell használni:

sed "/valami/d" file -> ebben az esetben minden olyan sort töröl, amiben szerepel a valami szó.

Szerintem két hiba van az  általad megadott fomában.

 

Az egyik (szintaktikai), hogy a szóköz karakter miatt nem annyira értelmes.

A másik (elvi), hogy a shell-ben idézőjelen belül a \-t is speciálisan értelmezi a shell (de csak bizonyos karakterek előtt!), szóval a te példád épp jó, de ha valaki másik karaktert ír a \ után, ajkor belefuthat nagy szopásba. Én e miatt leggyakrabban a , (vessző) karaktert használom, azaz a /minta/ helyett ezt írom: \,minta, .

Az általad írt megoldás helyes formája így néz ki:

sed "\A${f}Ad"

A sed tudtommal szöveges fájlok soronkénti manipulálását végzi. Amennyiben probléma az is hogy kitörölje a sort és ne csak egy newline-t hagyjon ott akkor más tool pl awk felé nézelődnék. Belefutottam hasonlóba, bár sed a problémák 90%-ban egyszerűbb volt (mivel awk-t mai napig nem tanultam meg rendesen), ellenben awk az igazi svájci bicska.

Én is AWK felé mentem volna első olvasásra a sed helyett. Esetleg egy megfelelően paraméterezett grep parancs is meg tudja talán oldani ezt.

Mivel az egész sort kellene törölni, ezért a sed sztem. nem feltétlen jó irány.

A tuti megoldás az awk lesz sztem.

A { print $0 } feleslegss, ugyanis az az alapértelmezett akció.

Jav: amúgy ez a -i  inplace hol létezik? A One-True-AWK. a mawk, a goawk és nálam a gawk manuálja sem említi.

Pont azt magyarázom, hogy a FreeBSD-hez bináris csomagból feltett gawk SEM ismeri.

Jav.

OK. A man-ban és a help-ben sem említi, de felismeri és működik is. Kösz, akkor tanultam egy fasza undoc featúrát.

Ismétlem: nincs benne a man gawk-ban és gawk --help -re sem említi. Persze tudom, a man gyengéknek való, ráadásul vérbeli GNU szoftver az info-ban dokumentálja a működést. (Most ellenőriztem, abban benne van, igaz nekem nincs telepítve info olvasó.)

Ugy vettem ki, hogy ez nem maga a gawk, hanem annak egy library-je. Azert kell -i-vel betolteni.

Ugyanaz, mint ha a python scriptedbe beimportalnal mondjuk egy numpy-t, annak a doksijat sem a man python-ban fogod megtalalni, hanem a neki megfelelo helyen.

A strange game. The only winning move is not to play. How about a nice game of chess?

Az lesz a gond ahogy most egy tesztfelületen megnéztem, hogy megcsinálja, csak nem írja bele a file-ba az értékeket. Viszont a második megoldásod temp file-al meg már értelmetlen, mert akkor az is kétsoros megoldés lesz, mint ahogy eredetileg megoldottam. Szerintem marad a sed, mert arra adtak jó megoldást, és érthető is a szintaktikája. Köszi a segítséget.

Igen, de mivel komplett útvonalak vannak/kerülnek bele a file-ba, ami ha egyezik törölni kell, és nem használok regexp-et keresésként, csak mplett sztringet, rész útvonal meg sosem kerül bele, így a sed-es megoldás tökéletesen működik. Most már 2 napja használom, sokféle esetben teszteltem, és rendben működik.

tr -d miért nem jó?

zászló, zászló, szív

Mert a tr nem regex alapú. Bizonyos patterneket elfogad a saját szintaxisában de az nem az extended re posix (ERE) vagy basic re posix (BRE) formátumú.

A sed ezeket támogatja.

Plusz itt sorok törléséről van szó vagyis az egész sort és a végén lévő esetleges új sor karakter(eket) is törölni kell. A sed "d" parancsa ezt csinálja, de a tr-nek nincsen fogalma arról hogy mi az a sor.