Este posibil să folosiți cumva funcția bash în AWK?
Exemplu de fișier (șir, int, int , int)
Mike 247808 247809 247810
Încercarea de a converti valorile din zecimal în hexazecimal.
Funcția definită fie în .bashrc
sau în script shell.
$ awk "{print $1 ; d2h($2)}" file awk: calling undefined function d2h input record number 1, file file source line number 1
Răspuns
Încercați să utilizați funcția system()
:
awk "{printf("%s ",$1); system("d2h " $2)}" file
În cazul dvs. system
apelați d2h 247808
și apoi adăugați ieșirea acestei comenzi la printf
ieșire:
Mike 3C800
EDIT:
Deoarece system
folosește sh
în loc de bash
Nu pot găsi o modalitate de a accesa .bashrc
. Dar puteți utiliza în continuare funcții din scriptul bash curent:
#!/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
EDIT 2:
Nu știu de ce, dar acest lucru nu funcționează pe Ubuntu 16.04. Acest lucru este ciudat, deoarece a funcționat pe Ubuntu 14.04.
Comentarii
Răspuns
Puteți apela bash din awk și utilizați ieșirea acestuia. Acest lucru este evident periculos din perspectiva performanței dacă se întâmplă prea des. Citând pagina de manual:
command | getline [var]
Rulați comanda canalizând ieșirea fie în $ 0, fie în var,
comanda ar fi un script bash care conține definiția funcției și execută funcția.
Răspuns
Conversia de la zecimal la hexazecimal este ceva ce awk
poate face foarte bine. Și ați putea defini o funcție awk
pentru a o face:
function d2h(d) { return sprintf("%x", d) }
Acum pentru a răspunde la întrebarea în cazul general, pentru ca awk
să ruleze bash
funcții, ar trebui să aveți awk
pentru a executa un shell bash
, care bash
pentru a interpreta definiția acelei funcții și a apela acea funcție, cu valoarea extrasă de awk
transmisă ca argumente.
Nu banal.
bash
acceptă exportul funcțiilor prin mediu, deci este disponibil în invocațiile ulterioare ale bash
, astfel încât să fie o modalitate de a trece definiția funcției la bash
invocată de awk
:
export -f d2h
Singurele modalități prin care awk
poate executa o comandă (bash
h ere) sunt cu system("cmd")
sau print... | "cmd"
sau "cmd" | getline
. În toate cazurile, awk
rulează un shell pentru a interpreta că cmd
, dar va fi sh
, nu bash
. Deci, trebuie să construiți o linie de comandă pentru sh
care este o invocație bash
care interpretează o bash
linie de comandă pentru a invoca funcția, deci trebuie să aveți grijă la citarea:
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))}"
Dacă doriți să obțineți ieșirea funcției în awk
, ar trebui să-l transferați înapoi printr-o conductă. Pentru aceasta, ar trebui să utilizați cmd | getline
în loc de system(cmd)
(care lasă stdout cmd
” neatins).
cmd | getline line
stochează o linie (strict vorbind o înregistrare , înregistrările fiind linii în mod implicit), deci pentru a obține întreaga ieșire în cazurile în care este format din mai multe linii, ai avea nevoie de o buclă precum:
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 ..."
Asta înseamnă să rulați câte un sh
și unul bash
pentru fiecare invocare a funcției , deci va fi destul de ineficient. Acest lucru ar ajunge să fie chiar mai mult ineficient decât ca bash
să citească și să împartă cu un while read loop
:
(unset -v IFS; while read -r a b rest; do printf "%s\n" "$a" d2h "$b" done < file)
De asemenea, rețineți că, de la Shellshock, bash
exportă acum funcții în variabile de mediu numite ca BASH_FUNC_d2h%%
. Unele sh
implementări, inclusiv mksh
și versiuni mai noi ale dash
eliminare acele variabile de mediu din mediu:
$ 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
Deci, în loc să vă bazați pe caracteristica de export a funcției slabe, puteți trece definiția funcției în alt mod. Ar putea fi printr-o variabilă de mediu cu un nume obișnuit:
BASH_FUNCTIONS=$(typeset -f d2h) awk " ... cmd = "exec bash -c "\""eval \"$BASH_FUNCTIONS\";" \ "d2h \"$1\""\"" bash " shquote($2) ..."
Răspuns
Încercați să faceți acest lucru:
awk "{print $1 ; printf "%x\n", $2}" file
AFAIK, nu puteți folosi un bash funcție în awk, dar numai un script. Puteți utiliza o funcție awk dacă este necesar.
Răspuns
Utilizarea unei funcții bash definite de utilizator inside awk
Disclaimer: Îmi dau seama că nu asta încearcă să facă OP, dar Google îi va conduce pe alții ca mine la acest răspuns.
Aveți un script bash
care este organizat cu funcții (deoarece nu vă urăști pe voi sau pe [majoritatea] colegilor) și cel puțin una dintre aceste funcții trebuie să sunați la altul din awk
.
Soluție
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
Comentarii
- eu reprezintă Queens, ea a fost crescută în Brooklyn
Răspuns
Doar un exemplu rapid pentru a demonstra @HaukeLaging „s command|getline
:
- permiteți introducerea să fie:
Dear friends my name is `id -nu` and today is `date "+%Y-%m-%d"`.
unde urmărim sintaxa shell, în intrare,
`command`
este folosit pentru a indica comenzi inline care trebuie înlocuite cu rezultatul execuția sa.
- Putem extinde comanda shell inline prin:
#!/usr/bin/gawk -f BEGIN { FS ="`"; } NF==3 { $2 | getline $2 } { print }
- Utilizare (după chmod obișnuit):
$ expand-inline input Dear friends my name is jjoao and today is 2018-01-15.
Răspuns
Acest lucru vă va oferi șanse mari.
cat ../logs/em2.log.1 |grep -i 192.168.21.15 |awk "{system("date"); print $1}"
funcția de sistem vă permite să analizați comanda bash în fluxul awk.
Răspuns
Acest răspuns este pentru GNU awk, dar alte versiuni pot implementa același truc. Ideea este că, atâta timp cât partea dreaptă a conductei este exact aceeași și nu „iese, awk nu închide conducta. Dar dacă este diferit, va deschide o nouă conductă. De exemplu, dacă tastați:
awk "BEGIN{ shell= "/bin/bash" } { print $0 | "/bin/bash" } END { print "echo $a" | " /bin/bash" }"
puteți tasta:
a=5 echo $a
și obțineți răspunsul așteptat (?) 5: nu a apărut nicio coajă nouă. Dar în secțiunea END, am tastat un spațiu suplimentar, astfel încât RHS-ul țevii este diferit și apare un nou shell fără nicio valoare pentru variabila a (și astfel se va imprima o linie goală la ieșire. Nu o pot găsi în documentație, dar modul recomandat de a utiliza conducte pe termen lung este așa cum am: pune comanda în secțiunea BEGIN într-o variabilă și refolosește acea variabilă. apoi refolosirea acestuia este un exercițiu lăsat în seama cititorului 🙂
d2h
au fost executabile, dar nu dacă funcția ‘ sa ” a fost definită fie în .bashrc, fie în scriptul shell „.source
), dar pot ‘ f figura de ce nu ‘ nu funcționează cu.bashrc
.$2
ajunge să fie interpretat ca un cod shell.export -f d2h
nu funcționează ‘ nu funcționează, o puteți face ca pentru ksh / zsh: (\ 42 și \ 47 sunt codurile de evacuare pentru ghilimele simple și duble)CODE=$(typeset -f d2h) awk ' { system("bash -c \47eval \42$CODE\42; d2h \42"$2"\42\47") }'