Használható valahogy az AWK belsejében a bash függvény?
Példa fájl (karakterlánc, int, int , int)
Mike 247808 247809 247810
Megpróbálja átalakítani az értékeket tizedestől hexadecimálissá.
A .bashrc
vagy shell szkriptben.
$ awk "{print $1 ; d2h($2)}" file awk: calling undefined function d2h input record number 1, file file source line number 1
Válasz
Próbálja használja a system()
függvényt:
awk "{printf("%s ",$1); system("d2h " $2)}" file
Az Ön esetében system
hívja meg d2h 247808
, majd csatolja a parancs kimenetét a printf
kimenethez:
Mike 3C800
SZERKESZTÉS:
Mivel system
a sh
szót használja a bash
Nem találok módot a .bashrc
elérésére. De továbbra is használhatja a jelenlegi bash szkript függvényeit:
#!/bin/bash d2h() { # do some cool conversion here echo "$1" # or just output the first parameter } export -f d2h awk "{printf("%s ",$1); system("bash -c "\""d2h "$2""\""")}" file
2. SZERKESZTÉS:
Nem tudom miért, de ez nem működik az Ubuntu 16.04-en. Ez furcsa, mert korábban az Ubuntu 14.04-en működött.
Megjegyzések
Válasz
Az awk-ból meghívhatja a bash-t, és használhatja annak kimenetét. Ez a teljesítmény szempontjából nyilvánvalóan veszélyes, ha túl gyakran fordul elő. A man oldal idézése:
command | getline [var]
Futtassa a kimenetet a $ 0 vagy a var változóba,
parancs egy bash szkript lenne, amely tartalmazza a függvény definícióját és végrehajtja a függvényt.
Válasz
A tizedestől hexadecimálissá konvertálás awk
nagyon jól meg tudja csinálni magát. És megadhat egy awk
függvényt:
function d2h(d) { return sprintf("%x", d) }
Most, hogy megválaszoljam a kérdést általános esetben, az awk
futtatásához a bash
function, akkor awk
kell egy bash
shell végrehajtásához, amely bash
a függvény definíciójának értelmezése és a függvény meghívása az awk
által kivont érték argumentumként való átadásával.
Nem triviális.
bash
támogatja a függvények exportálását a környezeten keresztül, így a bash
későbbi meghívásaiban elérhetővé válik, így ez az egyik út a bash
függvény meghatározása, amelyet awk
hívott meg:
export -f d2h
A awk
parancs végrehajtásának egyetlen módja (bash
h ere) a system("cmd")
vagy print... | "cmd"
vagy "cmd" | getline
. Minden esetben a awk
futtat egy héjat annak értelmezésére, hogy cmd
, de sh
, nem bash
. Tehát fel kell állítania egy parancssort sh
számára, amely egy bash
meghívás, amely egy bash
parancssor a függvény meghívásához, ezért vigyázni kell az idézéssel:
export -f d2h <file awk -v q=""" " function shquote(s) { gsub(q, q "\\" q q, s) return q s q } {print $1; system("exec bash -c "\""d2h \"$1\""\"" bash " shquote($2))}"
Ha a függvény kimenetét vissza akarja állítani a awk
, vissza kell vezetnie egy csövön keresztül. Ehhez a iv id = “helyett a cmd | getline
-t kell használni. 4be2d082e4 “>
(amicmd
” stdout-t érintetlenül hagyja).
cmd | getline line
egy sort tárol (szigorúan véve egy rekord , a rekordok alapértelmezés szerint sorok), tehát A teljes kimenet megszerzéséhez olyan esetekben, amikor több sorból áll, szükséged van egy hurokra, például:
awk "... cmd = "exec bash -c "\""d2h \"$1\""\"" bash " shquote($2) output = "" while ((cmd | getline line) > 0) { output = output line RS } sub(RS "$", "", output) # remove the last newline ..."
Ez azt jelenti, hogy egy sh
és egy bash
futtat a függvény minden egyes meghívásához , így elég hatástalan lesz. Ez még lényegesen hatástalanabb lenne, mint ha bash
elvégezné az olvasást és az osztást egy while read loop
:
(unset -v IFS; while read -r a b rest; do printf "%s\n" "$a" d2h "$b" done < file)
Vegye figyelembe azt is, hogy a shellshock óta a bash
exportál olyan funkciókat a környezeti változókba, amelyek neve: BASH_FUNC_d2h%%
. Néhány sh
megvalósítás, köztük mksh
és a dash
eltávolítás em újabb verziói > azok a környezeti változók a környezettől:
$ env "foo%%=bar" dash -c "printenv foo%%" $ env "foo%%=bar" mksh -c "printenv foo%%" $ env "foo%%=bar" zsh -c "printenv foo%%" bar $ env "foo%%=bar" bash -c "printenv foo%%" bar
Tehát ahelyett, hogy a gyenge függvény-exportálási funkcióra hagyatkozna, átadhatja a függvény-meghatározást más módon is. Lehet egy szokásos nevű környezeti változón keresztül:
BASH_FUNCTIONS=$(typeset -f d2h) awk " ... cmd = "exec bash -c "\""eval \"$BASH_FUNCTIONS\";" \ "d2h \"$1\""\"" bash " shquote($2) ..."
Válasz
Próbálkozzon ezzel:
awk "{print $1 ; printf "%x\n", $2}" file
AFAIK, nem használhat bash-t függvény az awk-ban, de csak egy szkript. Szükség esetén használhat egy awk függvényt is.
Válasz
A felhasználó által definiált bash függvény használata belül awk
Jogi nyilatkozat: Tudomásul veszem, hogy az OP nem ezt próbálja megtenni, de a Google a hozzám hasonló embereket is erre a válaszra vezeti.
Helyzet
Van egy bash
szkripted, amely funkciókkal van rendezve (mert nem utálod magad vagy [a legtöbb munkatársat]), és ezeknek a funkcióknak legalább 1-nek hívjon másikat a awk
belülről.
Megoldás
Script
#!/bin/env bash # The main function - it"s a sound pattern even in BASH main(){ # In the awk command I do some tricky things with single quotes. Count carefully... # The first $0 is outside the single quotes so it is the name of the current bash script. # The second $0 is inside the single quotes so it is awk"s current line of input. awk "{printf("%s. ", ++c); system(""$0" --do"); print $0}"<<-PRETEND_THIS_IS_AN_INPUT_STREAM and and well PRETEND_THIS_IS_AN_INPUT_STREAM } # functionized to keep things DRY doit(){ echo -n "doin" it " } # check for a command switch and call different functionality if it is found if [[ $# -eq 1 && $1 == "--do" ]]; then doit else main fi
Output
$ ./example.sh 1. doin" it and 2. doin" it and 3. doin" it well
megjegyzések
- I képviseli Queens-t, Brooklynban nevelték ki
Válasz
Csak egy gyors példa a @HaukeLaging “s bemutatására command|getline
:
- legyen a bemenet:
Dear friends my name is `id -nu` and today is `date "+%Y-%m-%d"`.
ahol a shell szintaxist követjük, akkor a bemenetben
`command`
jelöljük a inline parancsokat , amelyeket a végrehajtása.
- A soron belüli shell parancsot kibővíthetjük:
#!/usr/bin/gawk -f BEGIN { FS ="`"; } NF==3 { $2 | getline $2 } { print }
- Használat (a szokásos chmod után):
$ expand-inline input Dear friends my name is jjoao and today is 2018-01-15.
Válasz
Ez jó eséllyel jár.
cat ../logs/em2.log.1 |grep -i 192.168.21.15 |awk "{system("date"); print $1}"
A rendszerfunkció lehetővé teszi a bash parancs elemzését az awk adatfolyamban.
Válasz
Ez a válasz a GNU awk esetén, de más verziók is megvalósíthatják ugyanazt a trükköt. Az elképzelés az, hogy mindaddig, amíg a cső jobb oldala pontosan megegyezik és nem “kilép”, az awk nem csukja be a csövet. De ha ez más, akkor új csövet nyit. Például, ha beírja:
awk "BEGIN{ shell= "/bin/bash" } { print $0 | "/bin/bash" } END { print "echo $a" | " /bin/bash" }"
beírhatja:
a=5 echo $a
és kapja meg a várt (?) választ 5: nem született új héj. De az END szakaszban beírtam egy extra helyet, így a cső RHS-je eltér, és új héj keletkezik, amelynek nincs értéke az a változónak (és így egy üres sort nyomtat a kilépéskor. Nem találom a dokumentációval, de a hosszú távú csövek használatának ajánlott módja megegyezik a következővel: tegyem a parancsot a BEGIN szakaszba egy változóban, és használd újra ezt a változót.
Felhasználó által definiált függvény átadása egy bash munkamenetnek akkor az újrafelhasználása az olvasó számára hagyott gyakorlat 🙂
d2h
futtatható fájlok voltak, de nem, ha ‘ sa ” függvény definiálva vagy .bashrc vagy shell szkriptben “.source
útján), de ‘ f ábra miért nem ‘ működik a.bashrc
.$2
tartalmát végül shell kódként értelmezik.export -f d2h
nem működik ‘ t, ezt úgy is megteheti, mint a ksh / zsh esetében: (\ \ 42 és \ 47 az egyszerű és dupla idézőjelek menekülési kódjai)CODE=$(typeset -f d2h) awk ' { system("bash -c \47eval \42$CODE\42; d2h \42"$2"\42\47") }'