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