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
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
:
- 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.
- Voimme laajentaa sisäistä shell-komentoa seuraavasti:
#!/usr/bin/gawk -f BEGIN { FS ="`"; } NF==3 { $2 | getline $2 } { print }
- 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 🙂
d2h
olivat suoritettava tiedosto, mutta ei, jos se ’ sa ” -funktio määritettiin joko .bashrc- tai shell-komentosarjassa ”.source
kautta), mutta voin ’ f-kuvan miksi se ei toimi ’ ei toimi.bashrc
kanssa.$2
-sisällön sisältö tulkitaan lopulta shell-koodiksi.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") }'