Szkript átírása Perl-ről Awk-ra

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

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.


awk 'BEGIN {FS="|";OFS="\t"; } {match($5,"[[].*[]]");sp=substr($5,RSTART+1,RLENGT-2);print sp,$4,$2;}'

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.
gawk: warning: escape sequence `\[' treated as plain `['
gawk: warning: escape sequence `\]' treated as plain `]'
Egszer meg kéne már értenem, hogy mi ezzel a baj.
Ui: és ha valaki ismer még más, forrásban elérhető AWK-verziót, linket kérek.

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]

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.

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

Í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.

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 :-)