Usando a função bash shell dentro do AWK

16

É possível usar a função bash dentro do AWK de alguma forma?

Exemplo de arquivo (string, int, int, int)

Mike 247808 247809 247810

Tentando converter valores de decimal em hexadecimal.

Função definida em .bashrc ou em script de shell.

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

awk: chamando a função indefinida d2h  número de registro de entrada 1, arquivo de arquivo  número da linha de origem 1

    
por tiny 18.04.2013 / 21:46

7 respostas

15

Tente usar a função system() :

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

No seu caso, system chamará d2h 247808 e, em seguida, anexará a saída desse comando a printf output:

Mike 3C800

EDITAR:

Como system usa sh em vez de bash Não consigo encontrar uma maneira de acessar .bashrc . Mas você ainda pode usar funções do seu script atual:

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

Eu não sei porque, mas isso não está funcionando no meu Ubuntu 16.04. Isso é estranho, porque costumava trabalhar no Ubuntu 14.04.

    
por 22.09.2014 / 10:09
3

Tente fazer isso:

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

AFAIK, você não pode usar uma função bash no awk, mas apenas um script. Você pode usar uma função awk, se necessário.

    
por 18.04.2013 / 21:52
3

Você pode chamar o bash do awk e usar sua saída. Isso é obviamente perigoso do ponto de vista do desempenho se isso acontecer com muita frequência. Citando a página man:

command | getline [var]

Run command piping the output either into $0 or var,

O comando

seria um script bash que contém a definição da função e executa a função.

    
por 18.04.2013 / 22:02
3

Usando uma função bash definida pelo usuário dentro do awk

Aviso: Sei que não é isso que o OP está tentando fazer, mas o Google levará outras pessoas como eu a essa resposta.

Situação

Você tem um script bash que é organizado com funções (porque você não se odeia ou faz [mais] colegas de trabalho) e pelo menos uma dessas funções precisa chamar outro de awk .

Solução

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

Saída

$ ./example.sh
1. doin' it and
2. doin' it and
3. doin' it well
    
por 07.06.2016 / 20:57
2

awk pode executar awk funções. Para executar bash funções, você precisaria que awk executasse um bash shell, que bash interpretasse a definição dessa função e chamasse essa função, com o valor extraído por awk passado como argumentos.

Não é trivial.

bash suporta funções de exportação, portanto, está disponível em invocações subseqüentes de bash , portanto, é uma maneira de passar a definição da função para o bash chamado por awk :

export -f d2h

As únicas formas de awk executar um comando ( bash here) são com system("cmd") , ou print... | "cmd" ou "cmd" | getline . Em todos os casos, awk executa um shell para interpretar esse cmd , mas será sh , não bash . Então você precisa construir uma linha de comando para sh que é uma invocação bash que interpreta uma linha de comando bash para invocar a função, então você precisa ter cuidado com as citações:

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

Isso significa executar um sh e um bash para cada linha, portanto, será bastante ineficiente. Isso acabaria sendo significativamente mais ineficiente do que ter bash lendo e dividindo com while read loop :

(unset IFS; while read -r a b rest; do
  printf '%s\n' "$a"
  d2h "$b"
 done < file)
    
por 15.01.2018 / 13:20
0

Isso lhe dará boas chances.

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

função do sistema permite que você analise o comando bash no fluxo do awk.

    
por 15.01.2018 / 12:42
0

Apenas um truque rápido demonstra @HaukeLaging command|getline :

1) deixe a entrada ser:

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

Seguindo a sintaxe do shell, na entrada,

'command'

é usado para denotar comandos inline a serem substituídos pelo resultado de sua execução.

2) Podemos expandir o comando shell inline por:

#!/usr/bin/gawk -f

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

3) Uso (após o chmod usual):

$ expand-inline input
Dear friends
my name is jjoao and
today is 2018-01-15.
    
por 15.01.2018 / 15:27

Tags