web-dev-qa-db-fra.com

Utilisation de la fonction shell bash dans AWK

Est-il possible d'utiliser la fonction bash dans AWK d'une manière ou d'une autre?

Exemple de fichier (chaîne, int, int, int)

Mike 247808 247809 247810

Essayer de convertir des valeurs décimales en hexadécimales.

Fonction définie soit en .bashrc soit en script Shell.

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

awk: appel de la fonction non définie d2h entrée numéro d'enregistrement 1, fichier fichier source ligne numéro 1

27
tiny

Essayez d'utiliser la fonction system():

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

Dans votre cas, system appellera d2h 247808, puis ajoutez la sortie de cette commande à printf sortie:

Mike 3C800

ÉDITER:

Comme system utilise sh au lieu de bash Je ne trouve pas de moyen d'accéder à .bashrc. Mais vous pouvez toujours utiliser les fonctions de votre script bash actuel:

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

Je ne sais pas pourquoi, mais cela ne fonctionne pas sur mon Ubuntu 16.04. C'est étrange, car cela fonctionnait sur Ubuntu 14.04.

31
akarilimano

Vous pouvez appeler bash depuis awk et utiliser sa sortie. C'est évidemment dangereux du point de vue des performances si cela se produit trop souvent. Citant la page de manuel:

command | getline [var]

Exécutez la commande en redirigeant la sortie vers $ 0 ou var,

la commande serait un script bash qui contient la définition de la fonction et exécute la fonction.

9
Hauke Laging

awk peut exécuter les fonctions awk. Pour qu'il exécute les fonctions bash, vous aurez besoin de awk pour exécuter un shell bash, que bash pour interpréter la définition de cette fonction et appeler cette fonction, avec la valeur extraite par awk passée comme arguments.

Pas anodin.

bash prend en charge l'exportation de fonctions, il est donc disponible dans les invocations suivantes de bash, c'est donc une façon de transmettre la définition de la fonction au bash invoqué par awk :

export -f d2h

Les seuls moyens pour awk d'exécuter une commande (bash ici) sont avec sa system("cmd"), ou print... | "cmd" Ou "cmd" | getline. Dans tous les cas, awk exécute un Shell pour interpréter cela cmd, mais ce sera sh, pas bash. Vous devez donc construire une ligne de commande pour sh qui est une invocation bash qui interprète une ligne de commande bash pour appeler la fonction, vous devez donc être prudent en citant:

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

Cela signifie exécuter un sh et un bash pour chaque ligne, donc ça va être assez inefficace. Cela finirait par être encore plus inefficace que d'avoir bash à lire et à diviser avec un while read loop:

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

Essayez de faire ceci:

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

AFAIK, vous ne pouvez pas utiliser une fonction bash dans awk mais seulement un script. Vous pouvez utiliser une fonction awk si nécessaire.

5
Gilles Quenot

Utilisation d'une fonction bash définie par l'utilisateur dans awk

Disclaimer: Je me rends compte que ce n'est pas ce que le PO essaie de faire, mais Google mènera d'autres comme moi à cette réponse.

Situation

Vous avez un script bash qui est organisé avec des fonctions (parce que vous ne vous détestez pas ou [la plupart] des collègues) et au moins 1 de ces fonctions doit en appeler un autre depuis awk.

Solution

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

Sortie

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

Cela vous donnera de bonnes chances.

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

la fonction système vous permet d'analyser la commande bash dans un flux awk.

1
Mansur Ali

Juste un petit hack démontre @HaukeLaging command|getline:

1) que l'entrée soit:

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

En suivant la syntaxe Shell, en entrée,

`command`

est utilisé pour indiquer commandes en ligne à remplacer par le résultat de son exécution.

2) Nous pouvons développer la commande Shell en ligne en:

#!/usr/bin/gawk -f

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

3) Utilisation (après le chmod habituel):

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