Como chamar a função bash de dentro do awk?

2

Isso é um pouco complicado; Estou tentando descobrir a melhor abordagem para esse problema. Eu tenho algumas abordagens, mas elas parecem realmente hacky e eu gostaria de algo um pouco mais elegante.

Eu quero analisar um arquivo delimitado por espaço em branco, ignorando #comment lines e reclamando de qualquer linha não vazia que não tenha exatamente 4 campos. Isso é fácil o suficiente em awk :

awk '/^#/ {next}; NF == 0 {next}; NF != 4 {exit 1}; (dostuff)'

O truque é o que eu quero fazer com os dados, na verdade, é definido como variáveis em bash e, em seguida, executar uma função bash , a menos que $ 2 contenha um valor específico.

Aqui estão alguns pseudocódigos (principalmente idiomas reais, mas mistos) para explicar o que quero dizer:

# awk
/^#/ {next}
NF == 0 {next}
NF != 4 {exit 1}
$2 == "manual" {next}
# bash
NAME=$1
METHOD=$2
URL=$3
TAG=$4
complicated_bash_function_that_calls_lots_of_external_commands
# then magically parse the next line with awk.

Eu não sei como fazer isso sem algumas soluções feias, como chamar awk ou sed separadamente para cada linha do arquivo. (Originalmente eu coloquei a questão como "Como chamar a função bash de dentro do awk ou de cada linha de saída do awk de dentro do bash?")

Possivelmente funcionaria modificar a função bash em seu próprio script e fazê-la aceitar os argumentos 1, 2, 3, 4 como acima. Não sei como chamar isso de dentro do awk; daí meu título de pergunta.

O que eu gostaria de preferir , é ter tudo em um arquivo e torná-lo um script básico - chamando awk de bash em vez de bash de dentro de% código%. Mas ainda precisarei chamar a função awk de dentro do awk - uma vez para cada linha de não comentários do arquivo de entrada.

Como posso fazer isso?

    
por Wildcard 13.11.2015 / 03:01

2 respostas

3

Você pode ser capaz de fazer o que quiser colocando a saída de awk em um loop while read . Por exemplo:

awk '/^#/ {next}; NF == 0 {next}; NF != 4 {exit 1} ; {print}' | 
    while read NAME METHOD URL TAG ; do
        :  # do stuff with $NAME, $METHOD, $URL, $TAG
        echo "$NAME:$METHOD:$URL:$TAG"
    done

if [ "$PIPESTATUS" -eq 1 ] ; then
    : # do something to handle awk's exit code
fi

Testado com:

$ cat input.txt 
# comment
NAME METHOD URL TAG
a b c d
1 2 3 4
x y z
a b c d

$ ./testawk.sh <input.txt 
NAME:METHOD:URL:TAG
a:b:c:d
1:2:3:4

Observe que ele sai corretamente na quinta linha de entrada x y z .

    
por 13.11.2015 / 03:13
3

cas resposta é boa, mas se você realmente precisa analisar a saída no awk novamente e quer fazer isso de dentro do primeiro comando awk você tem uma sintaxe fantástica de comando pipe no awk:

awk '
{
  cmd = "echo name:tag:url:method" # (very simple example)
  while (cmd | getline)
  {
    #process output ($0)
    print
  }
  close(cmd)
}
'
    
por 17.11.2015 / 02:28