Je možné nějak použít funkci bash uvnitř AWK?
Příklad souboru (řetězec, int, int , int)
Mike 247808 247809 247810
Pokouší se převádět hodnoty z desítkových na šestnáctkové.
Funkce definovaná buď v .bashrc
nebo ve skriptu prostředí.
$ awk "{print $1 ; d2h($2)}" file awk: calling undefined function d2h input record number 1, file file source line number 1
Odpověď
Zkuste použijte system()
funkci:
awk "{printf("%s ",$1); system("d2h " $2)}" file
Ve vašem případě system
bude zavolejte d2h 247808
a poté připojte výstup tohoto příkazu k printf
výstupu:
Mike 3C800
EDIT:
Protože system
používá sh
místo bash
Nemohu najít způsob přístupu k .bashrc
. Stále však můžete používat funkce z vašeho aktuálního bash skriptu:
#!/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:
Nevím proč, ale to nefunguje na mém Ubuntu 16.04. To je zvláštní, protože to dříve fungovalo na Ubuntu 14.04.
Komentáře
Odpověď
Můžete volat bash z awk a použít jeho výstup. To je z hlediska výkonu zjevně nebezpečné, pokud k němu dochází příliš často. Cituji manuálovou stránku:
command | getline [var]
Spusťte příkaz, který výstup přesměruje na $ 0 nebo var,
příkaz by byl bash skript, který obsahuje definici funkce a provede funkci.
Odpovědět
Převod z desítkového na šestnáctkový je něco, co awk
dokáže velmi dobře. K tomu můžete definovat funkci awk
:
function d2h(d) { return sprintf("%x", d) }
Chcete-li nyní odpovědět na otázku obecně, pro awk
spustit bash
musíte awk
spustit bash
shell, který bash
interpretovat definici této funkce a volat tuto funkci s hodnotou extrahovanou awk
předanou jako argumenty.
Není triviální.
bash
podporuje funkce exportu přes prostředí, takže je k dispozici v následných vyvoláních bash
, takže je jen jeden způsob, jak předat definice funkce bash
vyvolaná awk
:
export -f d2h
Jediné způsoby, jak awk
provést příkaz (bash
h ere) are with its system("cmd")
, nebo print... | "cmd"
nebo "cmd" | getline
. Ve všech případech awk
spustí prostředí pro interpretaci cmd
, ale bude to sh
, nikoli bash
. Musíte tedy zkonstruovat příkazový řádek pro sh
, což je bash
vyvolání, které interpretuje bash
příkazový řádek k vyvolání funkce, takže při citování musíte být opatrní:
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))}"
Pokud chcete získat výstup funkce zpět do awk
, musíte jej přenést zpět pomocí potrubí. K tomu použijete cmd | getline
místo system(cmd)
(který ponechá cmd
“ standardní výstup nedotčený).
cmd | getline line
ukládá jeden řádek (přísně vzato jeden záznam , záznamy jsou standardně řádky), takže Chcete-li získat celý výstup v případech, kdy je sestaven z několika řádků, potřebujete smyčku, například:
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 ..."
To znamená spuštění jednoho sh
a jednoho bash
pro každé vyvolání funkce , takže to bude docela neefektivní. To by nakonec bylo ještě podstatně neefektivnější, než kdyby bash
provedli čtení a rozdělení pomocí while read loop
:
(unset -v IFS; while read -r a b rest; do printf "%s\n" "$a" d2h "$b" done < file)
Všimněte si, že od aplikace Shellshock nyní bash
exportují funkce v proměnných prostředí, které jsou pojmenovány jako BASH_FUNC_d2h%%
. Některé sh
implementace včetně mksh
a novějších verzí dash
remove tyto proměnné prostředí z prostředí:
$ 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
Takže místo spoléhání se na funkci exportu chabých funkcí můžete definici funkce předat jiným způsobem. Může to být pomocí proměnné prostředí s obvyklým názvem:
BASH_FUNCTIONS=$(typeset -f d2h) awk " ... cmd = "exec bash -c "\""eval \"$BASH_FUNCTIONS\";" \ "d2h \"$1\""\"" bash " shquote($2) ..."
Odpovědět
Zkuste to udělat:
awk "{print $1 ; printf "%x\n", $2}" file
AFAIK, nemůžete použít bash funkce v awk, ale pouze skript. V případě potřeby můžete použít funkci awk.
Odpověď
Použití uživatelem definované funkce bash inside awk
Zřeknutí se odpovědnosti: Uvědomuji si, že to není to, o co se OP snaží dělat, ale Google k této odpovědi přivede další, jako jsem já.
Situace
Máte bash
skript, který je uspořádán s funkcemi (protože nenávidíte sebe nebo [většinu] spolupracovníků) a alespoň 1 z těchto funkcí musí být zavolat další z awk
.
Řešení
Skript
#!/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
Výstup
$ ./example.sh 1. doin" it and 2. doin" it and 3. doin" it well
Komentáře
- já reprezentovat Queens, byla vychována v Brooklynu
Answer
Jen rychlý příklad pro ukázku @HaukeLaging command|getline
:
- ať je vstup:
Dear friends my name is `id -nu` and today is `date "+%Y-%m-%d"`.
kde sledujeme syntaxi shellu, na vstupu se
`command`
používá k označení vložených příkazů , které mají být nahrazeny výsledkem jeho provedení.
- Příkaz inline shellu můžeme rozšířit o:
#!/usr/bin/gawk -f BEGIN { FS ="`"; } NF==3 { $2 | getline $2 } { print }
- Použití (po obvyklém chmod):
$ expand-inline input Dear friends my name is jjoao and today is 2018-01-15.
Odpovědět
To vám dá dobré šance.
cat ../logs/em2.log.1 |grep -i 192.168.21.15 |awk "{system("date"); print $1}"
systémová funkce vám umožní analyzovat příkaz bash ve streamu awk.
Odpověď
Tato odpověď platí pro GNU awk, ale i jiné verze mohou implementovat stejný trik. Myšlenka je, že pokud je pravá strana potrubí přesně stejná a nevychází z ní, awk nezavírá potrubí. Pokud je to však jiné, otevře se nové potrubí. Například pokud zadáte:
awk "BEGIN{ shell= "/bin/bash" } { print $0 | "/bin/bash" } END { print "echo $a" | " /bin/bash" }"
můžete zadat:
a=5 echo $a
a získat očekávanou (?) odpověď 5: nebyl vytvořen žádný nový shell. Ale v části KONEC jsem zadal další prostor, takže RHS potrubí je jiný a nový shell je vytvořen bez hodnoty pro proměnnou a (a tak při výstupu vytiskne prázdný řádek. Nemohu ho najít v dokumentace, ale doporučený způsob použití dlouhodobých potrubí je takový, jaký mám: vložte příkaz do sekce ZAČÁTEK do proměnné a tuto proměnnou znovu použijte.
Poskytnutí uživatelem definované funkce relaci bash a pak opětovné použití je cvičení ponechané čtenáři 🙂
d2h
byl spustitelný soubor, ale ne, pokud je ‚ sa “ funkce definována buď v .bashrc, nebo ve skriptu prostředí „.source
), ale mohu ‚ f obrázek proč to ‚ nefunguje s.bashrc
.$2
se nakonec interpretuje jako kód shellu.export -f d2h
nefunguje ‚, můžete to udělat jako pro ksh / zsh: (\ 42 a \ 47 jsou únikové kódy pro jednoduché a dvojité uvozovky)CODE=$(typeset -f d2h) awk ' { system("bash -c \47eval \42$CODE\42; d2h \42"$2"\42\47") }'