Bash-kuoritoiminnon käyttäminen AWK: n sisällä

Voiko bash-toimintoa käyttää AWK: n sisällä jotenkin?

Esimerkkitiedosto (merkkijono, int, int , int)

Mike 247808 247809 247810 

Yritetään muuntaa arvot desimaalista heksadesimaaliksi.

Toiminto määritetään joko kohdassa .bashrc tai shell-komentosarjassa.

$ awk "{print $1 ; d2h($2)}" file awk: calling undefined function d2h input record number 1, file file source line number 1 

Vastaa

Yritä käytä system() -toimintoa:

awk "{printf("%s ",$1); system("d2h " $2)}" file 

Sinun tapauksessasi system Kutsu d2h 247808 ja liitä sitten tämän komennon lähtö printf -lähtöön:

Mike 3C800 

MUOKKAA:

Koska system käyttää sh bash En löydä tapaa käyttää .bashrc. Mutta voit silti käyttää nykyisen bash-komentosarjosi toimintoja:

#!/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 

MUOKKAA 2:

En tiedä miksi, mutta tämä ei toimi Ubuntu 16.04: lla. Tämä on outoa, koska se toimi aiemmin Ubuntu 14.04 -käyttöjärjestelmässä.

Kommentit

  • Tämä voisi toimia, jos d2h olivat suoritettava tiedosto, mutta ei, jos se ’ sa ” -funktio määritettiin joko .bashrc- tai shell-komentosarjassa ”.
  • @MichaelHomer kyllä, olet oikeassa. Kommenttisi ansiosta tajusin, että olen vastannut kysymykseen, jota kukaan ei esittänyt. Mutta olen löytänyt tavan käyttää funktioita nykyisestä komentosarjasta (ja mahdollisesti muista komentosarjoista source kautta), mutta voin ’ f-kuvan miksi se ei toimi ’ ei toimi .bashrc kanssa.
  • Että ’ s myös komento-injektiohaavoittuvuuden, koska $2 -sisällön sisältö tulkitaan lopulta shell-koodiksi.
  • Jos export -f d2h ei toimi ’ ei toimi, voit tehdä sen kuten ksh / zsh: lle ((\ 42 ja \ 47 ovat yksinkertaisten ja kaksoislainausten pakokoodit) CODE=$(typeset -f d2h) awk ' { system("bash -c \47eval \42$CODE\42; d2h \42"$2"\42\47") }'

Vastaa

Voit soittaa bashille awk: stä ja käyttää sen lähtöä. Se on tietysti vaarallista suorituskyvyn kannalta, jos sitä tapahtuu liian usein. Lainataan man-sivua:

command | getline [var] 

Suorita komento, joka johtaa lähdettä joko $ 0: een tai var: iin,

-komento olisi bash-komentosarja, joka sisältää funktion määritelmän ja suorittaa toiminnon.

Vastaa

Muunto desimaalista heksadesimaaliksi on asia, jonka awk voi hyvin tehdä itse. Ja voit määrittää awk toiminnon sen tekemistä varten:

 function d2h(d) { return sprintf("%x", d) }  

Nyt vastaamaan kysymykseen yleisessä tapauksessa, jotta awk suoritettaisiin bash -toiminnot, tarvitset awk suorittaaksesi bash -kuoren, joka bash tulkita funktion määritelmää ja kutsua funktio siten, että awk: n poimima arvo välitetään argumentteina.

Ei vähäpätöinen.

bash tukee toimintojen vientiä ympäristön kautta, joten se on käytettävissä seuraavissa bash -tapahtumissa, jotta ”yksi tapa siirtää bash -funktion määritelmä, jonka awk:

export -f d2h 

Ainoat tapat awk suorittaa komento (bash h ere) ovat sen system("cmd") tai print... | "cmd" tai "cmd" | getline kanssa. Kaikissa tapauksissa awk suorittaa komentotulkin tulkitsemaan cmd, mutta se on sh, ei bash. Joten sinun on rakennettava komentorivi sh, joka on bash -kutsu, joka tulkitsee bash komentorivi funktion kutsumiseksi, joten sinun on oltava varovainen lainaamalla:

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))}" 

Jos haluat palauttaa funktion lähdön kohtaan awk, sinun on siirrettävä se takaisin putken kautta. Tätä varten sinun on käytettävä cmd | getline (joka jättää cmd” -tunnuksen koskemattomaksi).

cmd | getline line tallentaa yhden rivin (tarkalleen ottaen yhden tietueen , tietueet ovat oletusarvoisesti rivejä), joten saadaksesi koko tuotoksen tapauksissa, joissa se koostuu useammasta rivistä, tarvitset silmukan, kuten:

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

Tämä tarkoittaa sitä, että suoritetaan yksi sh ja yksi bash jokaisen funktion kutsuun. , joten tulee olemaan varsin tehoton. Se olisi lopulta huomattavasti tehotonta kuin bash lukeminen ja jakaminen while read loop:

(unset -v IFS; while read -r a b rest; do printf "%s\n" "$a" d2h "$b" done < file) 

Huomaa myös, että shellshockin jälkeen bash vie nyt toimintoja ympäristömuuttujiin, joiden nimi on BASH_FUNC_d2h%%. Jotkut sh toteutukset, mukaan lukien mksh ja uudemmat versiot dash poista nämä ympäristömuuttujat ympäristöstä:

$ 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 

Joten sen sijaan, että luotettaisiin heikkoon funktioiden vientitoimintoon, voit siirtää funktion määritelmän jollakin muulla tavalla. Se voi tapahtua ympäristömuuttujan kautta, jolla on tavallinen nimi:

 BASH_FUNCTIONS=$(typeset -f d2h) awk " ... cmd = "exec bash -c "\""eval \"$BASH_FUNCTIONS\";" \ "d2h \"$1\""\"" bash " shquote($2) ..."  

Vastaa

Yritä tehdä tämä:

awk "{print $1 ; printf "%x\n", $2}" file 

AFAIK, et voi käyttää bashia toiminto awk: ssä, mutta vain komentosarja. Voit käyttää awk-toimintoa tarvittaessa.

Vastaa

Käyttäjän määrittämän bash-funktion käyttäminen sisällä awk

Vastuuvapauslauseke: Ymmärrän, että OP ei yritä tehdä sitä, mutta Google johtaa muut kaltaiset tähän vastaukseen.

Tilanne

Sinulla on bash -komentosarja, joka on järjestetty toiminnoilla (koska et vihaa itseäsi tai [useimpia] työtovereitasi) ja vähintään yhden näistä toiminnoista on soita toiselle awk.

Ratkaisu

Skripti

#!/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 

Tulos

$ ./example.sh 1. doin" it and 2. doin" it and 3. doin" it well 

Kommentit

  • I edustaa Queensia, hänet kasvatettiin Brooklynissa.

Vastaa

Vain lyhyt esimerkki @HaukeLagingin esittelystä command|getline:

  1. anna syötteen olla:
Dear friends my name is `id -nu` and today is `date "+%Y-%m-%d"`. 

missä seuraamme kuoren syntaksia, syötteessä

`command` 

käytetään merkitsemään sisäisiä komentoja , jotka korvataan hänen suorituksensa.

  1. Voimme laajentaa sisäistä shell-komentoa seuraavasti:
#!/usr/bin/gawk -f BEGIN { FS ="`"; } NF==3 { $2 | getline $2 } { print } 
  1. Käyttö (tavallisen chmodin jälkeen):
$ expand-inline input Dear friends my name is jjoao and today is 2018-01-15. 

vastaus

Tämä antaa sinulle hyvät mahdollisuudet.

cat ../logs/em2.log.1 |grep -i 192.168.21.15 |awk "{system("date"); print $1}" 

järjestelmän toiminnon avulla voit jäsentää bash-komennon awk-virrassa.

vastaus

Tämä vastaus, jos kyseessä on GNU awk, mutta muut versiot voivat toteuttaa saman temppun. Ajatuksena on, että niin kauan kuin putken oikea puoli on täsmälleen sama ja ei ”poistu”, awk ei sulje putkea. Mutta jos se on erilainen, se avaa uuden putken. Jos esimerkiksi kirjoitat:

awk "BEGIN{ shell= "/bin/bash" } { print $0 | "/bin/bash" } END { print "echo $a" | " /bin/bash" }" 

voit kirjoittaa:

a=5 echo $a 

ja saada odotettu (?) vastaus 5: uutta kuorta ei syntynyt. Mutta END-osaan kirjoitin ylimääräisen tilan, joten putken RHS on erilainen ja uusi kuori syntyy ilman arvoa muuttujalle a (ja tulostaa siten tyhjän rivin poistuttaessa. En löydä sitä dokumentaatio, mutta suositeltu tapa käyttää pitkäaikaisia putkia on kuten minäkin: laita komento muuttujan BEGIN-osioon ja käytä muuttuja uudelleen.

Käyttäjän määrittämän toiminnon antaminen bash-istunnolle ja sitten sen uudelleenkäyttö on lukijalle jätetty harjoitus 🙂

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *