Sziasztok!
Van egy olyan problémám, hogy egy log fájlból kellene bash scriptel kiszedni bizonyos részeket.
A részek < és > karakter között vannak. A < és > karakterekkel együtt kellene eltávolítanom.
Arra gondoltam, hogy egy tömbszerűségben meg lehetne adni azokat a részeket amiket ki akarok szedni, és a végeredményt egy másik fájlba menteném.
Ha valaki tudna segíteni, megköszönném.
- 3143 megtekintés
Hozzászólások
sed 's/<[^<]*>//g'
Már, ha jól értem. Ez valami házi feladat?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Dehogy, csak van egy log amibol muveszet kivalogatni az ertelmeset. Megprobalom, koszi.
=> Ubuntu User <=
- A hozzászóláshoz be kell jelentkezni
Minimálisan kipróbáltam:
sed 's/<[^<]*>//g' <<<"<a valami>link</a> nem link<body> test</body>"
link nem link test
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Nem vagyok nagy scriptes, osszerakod egy scriptbe?
probalkoztam, de nem jott ossze.
csinaltam 1 valtozot az eredeti file-ra, hogy megnyissa es abban irja at
aztan a kesz anyagot egy masik fajlba mentse, de nem csinal semmit.
=> Ubuntu User <=
- A hozzászóláshoz be kell jelentkezni
Persze.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Megkoszonnem, ha megosztanad velem. :)
=> Ubuntu User <=
- A hozzászóláshoz be kell jelentkezni
Nem vagyok olyan gyors. ;)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Ezt nem értem: [^<]*
Ha greedy (nem tudom, hogy az-e), akkor [^>]*, egyébként meg .*
- A hozzászóláshoz be kell jelentkezni
#!/bin/bash
myname="${0##*/}"
if [ $# -ne 1 ]; then
echo "$myname <infile>" >&2
exit 1
fi
if ! [ -f "$1" -a -r "$1" ]; then
echo "A(z) '$1' bemeneti file nem olvasható" >&2
exit 1
fi
sed 's/<[^<]*>//g' "$1"
exit 0
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Az szep, en eddig jutottam el, es vegulis van eredmeny is:
file=`cat log.file`
sed 's/<[^<]*>//g' <<< "$file" >> logs.file
=> Ubuntu User <=
- A hozzászóláshoz be kell jelentkezni
Majdnem jó:
file='log.file'
sed 's/<[^<]*>//g' "$file" >>'logs.file'
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
sed 's/<[^<]*>//g' log.file >> logs.file
nem kell cat, nem kell külön változó.
Egyébként nem teljesen értem a dolgot. Ha van egy ilyen sor:
bla1 < cucc1 > bla2 < cucc2 > bla3
akkor miért nem lesz az eredmény „bla1 bla3” ?
int getRandomNumber() { return 4; } // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű. xkcd
- A hozzászóláshoz be kell jelentkezni
Teljesen jó:
sed 's/<[^<]*>//g' <<<'bla1 < cucc1 > bla2 < cucc2 > bla3'
bla1 bla2 bla3
A bla2-t miért hagytad ki az elvárásaid közül?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Így jobban megnézve a parserem hibázott, my bad. Általában a 's/<[^>]*>//g' mintát szoktam ellenőrizni, de alapvetően valóban nincs különbség.
int getRandomNumber() { return 4; } // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű. xkcd
- A hozzászóláshoz be kell jelentkezni
Valóban az a jó, amit Te írtál. Valójában azt nem értem, az enyém mitől működött. :)
Hiszen, ha jól gondolom, a [^<] illeszkedik a > jelre, így azon túl kellene mennie, nem?
Lényegében azt akartam írni, amit Te, s nem értem, miért nem azt írtam, azt meg végképp nem értem, mégis mitől működik. Nem szeretem, ha valami úgy működik, hogy nem értem, miért teszi.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Alapvetően annyit akarunk ellenőrizni, hogy a < és a > egy „HTML tag” részét képezze. Amennyiben a stringünk nem tartalmaz <…<…>-hez hasonló anomáliákat (amiket azt hiszem, az SGML egyébként enged), kb. mindegy, hogy a tagnyitó <-re, vagy a taget záró >-ra keresünk a vélt tagen belül. Szerintem legalábbis.
A tagekre matcheltetést mostanában már általában nem szoktam végiggondolni, talán sajnos.
int getRandomNumber() { return 4; } // ← aláírás
//szabályos kockadobással választva. garantáltan véletlenszerű. xkcd
- A hozzászóláshoz be kell jelentkezni
Pedig benned volt minden reményem, hogy megtudjam. Mert szerintem én írtam marhaságot, s nem értem, mitől működik. Persze, azt tegyük fel, hogy tag-en belül nincs kacsacsőr. Ugya nekem az a bajom, hogy amikor eléri a záró kacsacsőrt, akkor a [^<] erre éppen úgy illeszkedik, mint a tag bármely belső karakterére, tehát tovább kellene mennie a match-nek a következő nyitó tag-ig.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Véletlenül pont működik így is. :) De azért a hatékonyság miatt jobb a
<[^>]*>
, mint a
<[^<]*>
, mert utóbbi esetben a
<tag>hosszuszoveg</tag>
illesztésekor a regexp engine előszőr elmegy záró tag elejéig a * miatt, onnan pedig length(hosszuszoveg) lépésszámú backtracking-et kell végrehajtania, hogy megtalálja amit keres. És ezt minden egyes tagnél.
Persze biztosan valahogy optimalizálják az okosak az ilyen sed meg hasonló cuccokat, szóval lehet hogy mégsem számít. :)
- A hozzászóláshoz be kell jelentkezni
Most, hogy írtad, rájöttem, hogy mitől működik az én változatom. Hiába megy első körben el a záró tag elejéig, a > jelre illeszkedés nem lesz meg, csak akkor, ha valóban visszamegy az első tag végéig. Ez nem esett le elsőre.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
"
<[^<]*>
...
<tag>hosszuszoveg</tag>
illesztésekor a regexp engine előszőr elmegy záró tag elejéig a * miatt,"
Nincs miért elmennie. Szó szerint leíratik neki, hogy kisebbjelet követő akárhány nemkisebbjel után legyen egy nagyobbjel, ez pedig (ahogy fentebb utalt vki erre), pont ugyanúgy az adott nyitó/záró tagen belül azonnal illeszkedik, mint a másik felfogás, ha nincs matrjoskaszerű tag. Ilyenkor a két megoldás teljesen ekvivalens.
- A hozzászóláshoz be kell jelentkezni
Szerintem is el kell menjen a következő tag nyitó kacsacsőréig, hiszen az illeszkedés a legbővebb halmazra történik:
sed 's/<.*>//g' <<<'<a tag>egy</a> ketto<b tag> harom</b> negy'
negy
Ha úgy lenne, ahogy írod, akkor ez is azt csinálná, ami az eredeti feladat volt. Az más kérdés, hogy amikor elmegy a nyitó kacsacsőrig, ott döbben rá, hogy nem teljesül az illeszkedés, s közben volt egy olyan lehetősége, ahol meg igen.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Nem. Azaz értem, hogy mire gondoltok, de kizárt, hogy erre az egyszerű esetre (karakterenként keresek nemXvalamik után Yvalamit) ne volna optimalizálva az re.
- A hozzászóláshoz be kell jelentkezni
A * greedy, megpróbálja a lehető legtöbbet beletenni a találatba.
<.*> esetén a legelső < és a legutolsó > és minden, ami közöttük van lesz a találat.
http://www.regular-expressions.info/repeat.html
A google regexp greedy non greedy keresésre ez az első.
- A hozzászóláshoz be kell jelentkezni
Ne keverd a felhozott (rossz) <.*> példát a fent tárgyalttal!
A .* és [^>]* között tényleg nincs nagy különbség, de ha fejben leprogramozod, hogy egyszerű substr-ekkel meddig tartana megtalálni egy minta elejét az egyikkel és a másikkal, kiderül, hogy mégis hatalmas az a diffi.
- A hozzászóláshoz be kell jelentkezni
Az a példa szándékosan rossz, a magyarázat része.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Sajnos nem ekvivalensek. Értem a gondolatmenetedet, de mint ahogy mások is írták, a '*' greedy. Ezért hiába találja meg az egyezést, az elején, definíció szerint tovább kell mennie (kötelezően) mindaddig, míg a megelőző részkifejezés illeszkedik. Tehát ha a példában ezt írtam volna:
<tag>nemjolformalt>xml</tag>
Akkor az illeszkedés
<tag>nemjolformalt>
lenne, és még ráadásul backtracking-gel megfűszerezve, mert így is elmenne a záró tag elejéig.
- A hozzászóláshoz be kell jelentkezni
Kimenete az stdout, tehát ha a script neve tagremove, az aktuális könyvtárban van, van rá futtatási jog, akkor így használható:
./tagremove /itt/van/a/logfile/log.txt >eredmeny.txt
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Koszi szepen :)
=> Ubuntu User <=
- A hozzászóláshoz be kell jelentkezni
.
- A hozzászóláshoz be kell jelentkezni