it-swarm.com.de

Verwenden der Bash-Shell-Funktion in AWK

Ist es möglich, die Bash-Funktion in AWK irgendwie zu verwenden?

Beispieldatei (string, int, int, int)

Mike 247808 247809 247810

Es wird versucht, Werte von dezimal nach hexadezimal zu konvertieren.

Funktion, die entweder in .bashrc oder im Shell-Skript definiert ist.

awk '{print $1 ; d2h($2)}' file

awk: Aufruf der undefinierten Funktion d2h Eingabe Datensatz Nummer 1, Datei Datei Quellzeile Nummer 1

27
tiny

Versuchen Sie, die Funktion system() zu verwenden:

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

In Ihrem Fall ruft systemd2h 247808 Auf und hängt dann die Ausgabe dieses Befehls an die Ausgabe von printf an:

Mike 3C800

BEARBEITEN:

Da systemsh anstelle von bash verwendet, kann ich keinen Weg finden, auf .bashrc Zuzugreifen. Sie können jedoch weiterhin Funktionen aus Ihrem aktuellen Bash-Skript verwenden:

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

Ich weiß nicht warum, aber das funktioniert nicht auf meinem Ubuntu 16.04. Das ist seltsam, weil es früher unter Ubuntu 14.04 funktioniert hat.

31
akarilimano

Sie können bash von awk aus aufrufen und dessen Ausgabe verwenden. Das ist aus Sicht der Leistung offensichtlich gefährlich, wenn es zu oft vorkommt. Zitieren der Manpage:

command | getline [var]

Führen Sie den Befehl aus, der die Ausgabe entweder in $ 0 oder var weiterleitet.

befehl wäre ein Bash-Skript, das die Funktionsdefinition enthält und die Funktion ausführt.

9
Hauke Laging

awk kann awk Funktionen ausführen. Damit bash Funktionen ausgeführt werden können, benötigen Sie awk, um eine bash Shell auszuführen, die bash, um die Definition dieser Funktion zu interpretieren, und einen Aufruf diese Funktion, wobei der von awk extrahierte Wert als Argumente übergeben wird.

Nicht trivial.

bash unterstützt das Exportieren von Funktionen, sodass diese in nachfolgenden Aufrufen von bash verfügbar sind. Auf diese Weise können Sie die Definition der Funktion an das von bash aufgerufene awk übergeben. ::

export -f d2h

Die einzigen Möglichkeiten für awk, einen Befehl auszuführen (bash hier), sind system("cmd") oder print... | "cmd" Oder "cmd" | getline. In allen Fällen führt awk eine Shell aus, um cmd zu interpretieren, aber es wird sh sein, nicht bash. Sie müssen also eine Befehlszeile für sh erstellen, die ein bash -Aufruf ist, der eine bash -Befehlszeile interpretiert, um die Funktion aufzurufen. Daher müssen Sie beim Zitieren vorsichtig sein:

export -f d2h
<file awk -v q="'" '
  function shquote(s) {
    gsub(q, q "\\" q q, s)
    return q s q
  }
  {print $1; system("bash -c '\''d2h \"$1\"'\'' bash " shquote($2))}'

Das bedeutet, dass für jede Zeile ein sh und ein bash ausgeführt wird, was ziemlich ineffizient sein wird. Das wäre sogar noch wesentlich ineffizienter, als wenn bash das Lesen und Teilen mit einem while read loop Durchführen würde:

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

Versuchen Sie Folgendes:

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

AFAIK, Sie können in awk keine Bash-Funktion verwenden, sondern nur ein Skript. Bei Bedarf können Sie eine awk-Funktion verwenden.

5
Gilles Quenot

Verwenden einer benutzerdefinierten Bash-Funktion in awk

Haftungsausschluss : Mir ist klar, dass dies nicht das ist, was das OP versucht, aber Google wird andere wie mich zu dieser Antwort führen.

Situation

Sie haben ein bash -Skript, das mit Funktionen organisiert ist (weil Sie sich selbst oder [die meisten] Mitarbeiter nicht hassen), und mindestens eine dieser Funktionen muss eine andere aus awk heraus aufrufen.

Lösung

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

Ausgabe

$ ./example.sh
1. doin' it and
2. doin' it and
3. doin' it well
4
Bruno Bronosky

Dies gibt Ihnen gute Chancen.

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

mit der Systemfunktion können Sie den Befehl bash innerhalb des awk-Streams analysieren.

1
Mansur Ali

Nur ein kurzer Hack demonstriert @HaukeLaging command|getline:

1) Eingabe sei:

Dear friends
my name is `id -nu` and
today is `date "+%Y-%m-%d"`.

Nach der Shell-Syntax in der Eingabe

`command`

wird verwendet, um Inline-Befehle zu bezeichnen, die durch das Ergebnis seiner Ausführung ersetzt werden sollen.

2) Wir können den Inline-Shell-Befehl erweitern durch:

#!/usr/bin/gawk -f

BEGIN  { FS ="`";        }
NF==3  { $2 | getline $2 }
       { print           }

3) Verwendung (nach dem üblichen chmod):

$ expand-inline input
Dear friends
my name is jjoao and
today is 2018-01-15.
1
JJoao