Sziasztok!
Van egy perl scriptem, ami így néz ki:
#!/usr/bin/perl -w
use strict;
while(<>){
my @f=split(/\|/);
$f[4]=~/\[(.*)\]/;
my $sp=$1;
print "$sp\t$f[3]\t$f[1]\n";
}
Ez azt csinálja, hogy a bemenetről érkező sorokat szétvágja a | mezőelválasztóknál. Az 5. mezőből kiszedi a stringet, ami [ ] zárójelek között van, és berakja az sp változóba. aztán a végén kiírja tabbal szeparálva az sp változót, illetve a bemenetből a 4. és a 2. mezőt érintetlenül.
A szkript szépen le is fut, azt is csinálja, amit szeretnék, a nagy kérdés az az, hogy hogyan lehet ezt megcsinálni awk egysorosból? (Nem házi feladat, csak okosodni szeretnék.)
Köszi előre is,
Csaba
- 1328 megtekintés
Hozzászólások
Asszem, kb. ennyi:
awk -F'|' -vOFS='\t' '{sp=$5; gsub(/^\[|\]$/, "", sp); print sp, $4, $2}'
Persze ez nem csekkeli, hogy az 5. mező tényleg úgy néz-e ki, ahogy kell... ahogy az eredeti perl kód sem igazán.
- A hozzászóláshoz be kell jelentkezni
A gsub-od nagyon ügyes, de javítani kéne, mert ez nem pont azt csinálja, mint az eredeti (nem veszi észre, ha az 5. mezőben van valami a zárójelezett részen kívül). Szóval csak a gsub rész:
gsub(/^.*\[|\].*$/, "", sp);
- A hozzászóláshoz be kell jelentkezni
Szentigaz, sőt direkte abból indultam ki, hogy az egész mezőt a zárójelek határolják, pedig erről szó sem volt.
Nincs az az egyszerű specifikáció, amit félre ne lehetne érteni. :)
- A hozzászóláshoz be kell jelentkezni
awk 'BEGIN {FS="|";OFS="\t"; } {match($5,"[[].*[]]");sp=substr($5,RSTART+1,RLENGT-2);print sp,$4,$2;}'
- A hozzászóláshoz be kell jelentkezni
Igazad van, inkább ez a "szó szerinti" fordítás.
Az enyém "értelem szerinti".
- A hozzászóláshoz be kell jelentkezni
Javítani már nem sikerült, de értelem szerint az RLENGT helyett RLENGTH írandó :-)
- A hozzászóláshoz be kell jelentkezni
Még valami: eredetileg ezt terveztem írni (csak az ominózus rész) :
match($5,"\[.*\]");
Ez így szerintem sokkal átláthatóbb. Ellenben nem a kívánt eredményt adta, ezért írtam át. Azóta gyorsan teszteltem egyet - direkt ilyen célból fönn van nekem mind a 3 általam ismert, elérhető FOSS AWK-verzió (nawk - "The One True AWK" by Brian Kernighan, the K from awk; mawk - by Mike Brennan - és persze a gawk GNU Awk). Ebből egyedül a mawk csinálja azt amit várok tőle, az nawk és a gawk szerint nincs találat, a gawk ezen kívül még két warning-ot is kidob.
Egszer meg kéne már értenem, hogy mi ezzel a baj.
gawk: warning: escape sequence `\[' treated as plain `['
gawk: warning: escape sequence `\]' treated as plain `]'
Ui: és ha valaki ismer még más, forrásban elérhető AWK-verziót, linket kérek.
- A hozzászóláshoz be kell jelentkezni
Forrásos egyéb verziót nem tudok, de a zárójelekre van tippem.
Amikor nem konstans regexpet adsz meg (nem / jelek között szerepel), akkor a regexp effektív értéke a - perlben így mondanánk - sztringinterpoláció eredménye. Vagyis
"\[.*\]" = /[.*]/
, azaz egy nem túl értelmes karakterlista. Úgy látszik, az ilyen csúszós útszakaszra felhívják a figyelmet.
$ awk '{match($0,"\[.*\]"); print ">>" substr($0,RSTART,RLENGTH)}'
awk: warning: escape sequence `\[' treated as plain `['
awk: warning: escape sequence `\]' treated as plain `]'
ezt [nem fogja] megtalalni
>>
$ awk '{match($0,/\[.*\]/); print ">>" substr($0,RSTART,RLENGTH)}'
ezt [meg fogja] talalni
>>[meg fogja]
- A hozzászóláshoz be kell jelentkezni
Kötekedés on: ciklusban ugyanarra változóra my -t mondani enyhén szólva memóriapazarló. Idéznék a "Learning Perl" c. alapműből (The LLama book, 105. oldal, Exercises fölötti utolső bekezdés):
"... If you stick it inside a loop, you'll get brand new variable for each iteration of the loop, whch is pretty useless unless you like wasting memory ..."
Hozzátenném, fenti idézet nem a my, hanem a local operátorról szól, de tudtommal ebben nincs különbség a kettő közöt :-)
Jav: ja, és a while és split helyett -n és -a opciók (man perlrun) - igaz ekkor nem f, hanem F lesz a tömböd neve. De ez OT, mert nem a perl-ről, hanem az awk-ról kérdeztél.
- A hozzászóláshoz be kell jelentkezni
Hmm, köszi. Mindig tanul az ember....
Csaba
- A hozzászóláshoz be kell jelentkezni
She-bang sor értelemszerűen:
.../perl -wane
(ezt legalább meg lehet jegyezni)
Basszus, a split nem helyettesíthető, mert nem "\s" a szeparátor. Akkor ezt a felét visszavonom. (-a opció ugrik).
- A hozzászóláshoz be kell jelentkezni
Így megy, csak kevésbé megjegyezhető. :)
#!/usr/bin/perl -wanF\|
- A hozzászóláshoz be kell jelentkezni
> Basszus, a split nem helyettesíthető, mert nem "\s" a szeparátor.
- A hozzászóláshoz be kell jelentkezni
Hehe, és oda is van írva a -F a hivatkozott perlrun -ba. Akkor most nekem: RTFM!
- A hozzászóláshoz be kell jelentkezni
Egy picit továbbgondolva a cikluson belüli májolást: de az nem úgy van, hogy minden iterálás elején lefoglalja a memóriát, a végén meg felszabadítja?
(Meg ne kövezzetek a kérdésért, nem vagyok programozó. A scriptjeimnél ritkán kritérium a jó memóriagazdálkodás. Azért érdekel, hátha egyszer számít majd...)
Csaba
- A hozzászóláshoz be kell jelentkezni
Íme a válasz:
perl -e 'my $outer; for (my $i=1; $i<=5; ++$i) {my $inner; print \$outer, "\t", \$inner, "\n";}'
SCALAR(0x804d6f0) SCALAR(0x804d738)
SCALAR(0x804d6f0) SCALAR(0x804ccdc)
SCALAR(0x804d6f0) SCALAR(0x804cb44)
SCALAR(0x804d6f0) SCALAR(0x804d6d8)
SCALAR(0x804d6f0) SCALAR(0x804d738)
Ez egyébként nekem is tanulság, mert eddig nem azért tettem ki a változókat, mert ezt tételeztem fel, hanem csak mert nekem szebb, ha a ciklusban csak az van, amit tényleg csinálnia kell - ezentúl nem csak azért fogom.
- A hozzászóláshoz be kell jelentkezni
Nekem ebből nem következik az, hogy az $inner nem szabadul fel az iteráció végén, csak az, hogy minden iterációban máshol van a memóriában. Vagy tévedek? (Bocsáss meg a laikus kérdésért, ismétlem, nem vagyok programozó.)
Csaba
- A hozzászóláshoz be kell jelentkezni
Igazad van, ez Zahy sejtését volt hivatott alátámasztani, hogy a localra vonatkozó intelem igaz a myra is.
- A hozzászóláshoz be kell jelentkezni
Megnéztem, nálam is hasonlóan viselkedik. Sőt, local-lal is :-) Ebben az esetben azt kell mondjam, hogy a Llama könyv megírása óta - ami ugye még 4-es perl-ről szólt - javították ezt a ficsort.
- A hozzászóláshoz be kell jelentkezni
???
A kívül deklarált címe nem változik, a belül deklarált címe változik az ismételt helyfoglalások miatt.
Szóval a fenti intelmed helytálló.
... vagy én nem követem jól az eseményeket.
- A hozzászóláshoz be kell jelentkezni
Ha jobban megnezed, az 5. az mar ugyanaz, mint az elso. Ez gyanus lett, lefuttattam 50-ig, es nalam meg erdekesebb, mert kettesevel valtozik a cim. Paratlan futasnal X, paros futasnal X - sokkal arrebb helyezi, de mindig ugyanoda. Szoval nem tudom, nem vagyok annyira meggyozve, mint lehetnek :-)
- A hozzászóláshoz be kell jelentkezni
Simán megmagyaráztam magamnak azzal, hogy a heap lyukait listaként használja, vagyis az első elegendően nagy szabad helyre kerül, aminek kerülnie kell.
De láttunk már karón varjút. :)
- A hozzászóláshoz be kell jelentkezni
Köszönöm a megoldásokat, megy mind a kettő.
Csaba
- A hozzászóláshoz be kell jelentkezni