[Megoldva] awk kérdés

Van ez a részlet egy mencoder végén.

mencoder blabla
-o ${movie_path}_${_date}.avi 2>${movie_path}_${_date}_error.log | tee ${movie_path}_${_date}_message.log | awk -vFS='s' -vRS='\r' -vORS='\r' '/^Po/ {print " A felvétel aktuális ideje [mp]" $2}'

A kérdés hogy ez a szöveg: A felvétel aktuális ideje [mp] lehet-e valamilyen formában egy változóban?

Például: szoveg="A felvétel aktuális ideje [mp]"

Tehát csak a vége
'/^Po/ {print " ${szoveg}" $2}'

Az biztos hogy így nem működik.

Hozzászólások

Ha shell változót akarsz behelyettesíttetni, akkor meg kell szakítani az aposztrófos részt:

'/^Po/ { print "'"${szoveg}"'" $2}'

Lehet, de ezt nem tudtam átültetni a gyakorlatba, a topic nyitóban megadott feltételekkel.

A kezdő awk ez: (Ez amúgy egy mencoder kimenet feldolgozása.)
awk -vFS='s' -vRS='\r' -vORS='\r' '/^Po/ {print " A felvétel aktuális ideje [mp]" $2}'

A te példád:
a='Hello world'; awk -v szoveg="$a" 'BEGIN {print szoveg;}'

A próbálkozásom:
a="Valami"
awk -v szoveg="$a"-vFS='s' -vRS='\r' -vORS='\r' '/^Po/ ' BEGIN {print szoveg;}' $2}'

awk: cmd. line:1: fatal: cannot open file `BEGIN' for reading (Nincs ilyen fájl vagy könyvtár)
./probascript: sor: 355: } $2}: parancs nem található

Hogy ez utobit hogy hoztad ossze, azt nem tudom. Ami fenn elhangzik, hogy:

1) - adj meg egy opciot az awk-nak; ezt jol csinaltad a

-v szoveg="$a"

formaval

2) - es a sztringed helyett erre a valtozora hivatkozzal az awk-scripten belul. No ezt elrontottad. Osszesen annyit csinalj, hogy az eredeti awk kodban csereld le

{print " A felvétel aktuális ideje [mp]" $2}

szoveget

{print szoveg $2}

formara, es mennie kell (marmint az elso modositassal egyutt).


rizsa='Ingyom-bingyom tálibe, esetleg telibe: '
awk -v szoveg="$rizsa" -vFS='s' -vRS='\r' -vORS='\r' '/^Po/ {print szoveg $2}'

A BEGIN csak azért volt, hogy a demóm működjön, mivel a példámban semmit sem pipe-oltam az awk-nak, így a középső blokkban - amely tehát nem a BEGIN illetve END kulcsszavakkal kezdődik - várta volna az stdin-ről a feldolgozandó adatokat.

Persze a másik megoldás is jó, elő lehet állítani az awk scriptet dinamikusan, röptében is, csak minek, ha nem muszáj. Ha bash-ben írsz awk scriptet, szerintem így áttekinthetőbb:

awk_profiles=`cat <<'EOF'
    BEGIN {
        l=length(s);
        printf("%s=(", arrayname);
    }
    NR!=1 {
        printf(" ");
    }
    {
        printf("'%s'", substr($0, l+2));
    }
    END {
        printf(" '%s')\n", new);
    }
EOF`

ls -1d "$HOME/$PROFILEDIR"_* | awk -v s="$HOME/$PROFILEDIR" -v arrayname=p
rofilenames -v new="$new" "$awk_profiles"

Tegyük hozzá, ne keress értelmet a programban, mert csak azt a részt mutattam meg a Skype-hoz írt wrapper scriptemből, ami ebből a szempontból lényeges. Ugye nem egyetlen sorba zsúfoltam az awk scriptet, hanem átláthatóan definiáltam azt egy változóba, majd odaadtam az awk-nak egy helyettesítéssel. Összetettebb awk scriptet egyetlen sorban írni igen kellemetlen, átláthatatlan.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Basszus, minek ezt igy elbonyolitani?

awk_profiles='bla
meg
masik
bla'

Ennek a catolos izenek akkor lenne ertelme, ha EOF lenne es nem 'EOF' (mert akkor a shell meg beleszolhatna a helyettesitesbe, de igy pont ugyanazt kapod meg). En amugy teljesen elfogadhatonak tartom a

awk -opciok '
ize
mize
ecet' fajlok

format. De persze izlelesek es protonok.

Jogos, igazad van, string konstans esetén felesleges a here document alkalmazása. A lényeg az, hogy egy sorba írt awk script néhány zárójel után eléggé áttekinthetetlen, pláne, ha olyasmi van, mint a példában, hogy egy string tartalmaz zárójelet.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Különben bedőltem Neked. Azért érdemes bonyolítani, mert így a sor eleji EOF - vagy bármi, ami nincs a sor elején a script-ben - lesz a scriptet záró elem. Sima string esetén nem írhatok aposztrofot a string belsejébe, ami kellemetlen. Szóval jó ez a here document.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Azért van egy ritka eset, amikor here-docos megoldást választanám: ha maga a kód hemzsegne az aposztrófoktól, ami egyébként elég nyögvenyelős awk-ban.

Ez így még mindig szebb, mint bármilyen egyéb szükséges erőszaktevés:


$ PRG=`cat <<'EOF'
BEGIN { print "'aposztrofos szoveg'"}
> EOF`
$ awk "$PRG"
'aposztrofos szoveg'

+1

Nem ritka, ha megnézed, a példám éppen ilyen.

Akkor mostmár azt is leírom, hogy miért használtam ezt a script-et. Bash-ben igen nehéz kicsikarni pipe-ból változót, hiszen a pipe-ban futó programok önálló process-ben futnak, azok memóriaterületei a szülő számára nem elérhetők, a feldolgozás után a subshell kilép, a memóriaterület felszámolódik. Így aztán marad nagyjából az, hogy az stdout-on keresztül tud a subshell kommunikálni a szülőjével, vagy file-on keresztül, ami persze nagyjából ugyanaz.

A konkrét script-ben az awk programmal egy bash tömböt inicializáltam, csak nem akartam ezzel a kérdezőt összezavarni:

eval `ls -1d "$HOME/$PROFILEDIR"_* | awk -v s="$HOME/$PROFILEDIR" -v arrayname=profilenames -v new="$new" "$awk_profiles"`

A Skype-hoz azért készítettem wrapper script-et, mert több profilt is használok, s emlékeim szerint a Skype auto login esetén belép kérdés nélkül, ellenkező esetben viszont jelszót is írni kellene, s fogalmam sincs a jelszavamról, nem is érdekel. Tehát csak profilt választok a yad segítségével, aztán bemásolom a Skype alá a megfelelő .Skype alkönyvtárat, aztán futtatom a skype-ot. Továbbá bugos a Skype, néha elszáll, ha ritkán is, s ezzel a scripttel meg tudom dögleszteni előbb SIGTERM-et, halhatatlanság esetén SIGKILL-t küldve neki. Ehhez elég a desktop-on csak az ikonra kattintani, hiszen a scriptem kiszúrja, hogy fut már egy példányban a Skype. Ebből az is következik, hogy nem tudom több példányban elindítani, s ezzel az egyes példányok által szétbarmolni a profilt.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az eval kifejtése valami ilyesmit fog adni:

profilenames=('egyik' 'másik' '<New profile>')

Az egyik, másik a létező profilnevek. A yad-dal ezen listából lehet választani, illetve új profilt létrehozni.

Szerk.: A profilneveket pedig úgy állítom elő, hogy megnézem, milyen profilom van mentve. Nem használok konfig file-t, egyszerűen az ls kimenetéből állapítom meg a létező profilokat.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE