Awk: if e declaração condicional no mesmo bloco

2

Aqui está o código para um script onde devo verificar o nome do arquivo para ser 'pretempsc.cfg' e imprimir seu conteúdo como está. . Para qualquer outro arquivo, apenas modifique as linhas que começam com 'abc disable ...' para 'no abc ...'.

Eu só mergulhei os dedos do pé no awk agora mesmo, por favor, sofra com qualquer erro na terminologia ..

    #!/bin/sh
    IN_FILE=$1
    OUT_FILE=$2

    WhatFileIsIt() {
    awk -v filename=$IN_FILE '
    BEGIN {
        scnode = 0;
        if (filename == "pretempsc.cfg") {
            scnode = 1; }
    }
    {
        if (!scnode) {
            /^abc disable/ {
            print "no abc "$4"";
            next;
            }

            print;}
        }
        else {print}
    }
    '
    }

    cat $IN_FILE | WhatFileIsIt | cat > $OUT_FILE

Ao executar este script, recebo o seguinte erro:

 awk: cmd. line:9:         /^abc disable/ {
 awk: cmd. line:9:                        ^ syntax error
 awk: cmd. line:16:     else {print}
 awk: cmd. line:16:     ^ syntax error

Pelo que pude procurar, suspeito que estou errado no uso de if e condition-action dentro do bloco de ação, mas não consigo descobrir exatamente o que está errado.

Para notar: eu PRECISO usar o awk dentro do shell script, e há muitas outras funções similares a WhatFileIsIt fazendo o próprio processamento no IN_FILE.

    
por StudentForLife 22.09.2016 / 16:28

1 resposta

2

Sim, você precisa alterar essa correspondência de padrão para uma declaração if completa:

if (/^abc disable/) {
    print "no abc "$4"";
    next;
}

( /pattern/ é a abreviação de $0 ~ /pattern/ , em que $0 contém toda a linha de entrada.)

Observe que print só imprime a quarta coluna da entrada depois de no abc , portanto, abc disable foo bar doo se transforma em apenas no abc bar . Não tenho certeza se é isso que você queria.

Enquanto estamos nisso, algumas outras coisas vêm à mente ... Sinta-se à vontade para ignorar qualquer coisa, se elas forem óbvias demais ou entrarem em conflito com o resto do seu roteiro. (E vamos esperar que eu não tenha cometido muitos erros.)

Eu acho que há um suporte extra no final do print , e parece que o recuo da condição mais profunda está um pouco errado, portanto, um pouco de reescrita:

{
    if (!scnode) {
        if (/^abc disable/) {
            print "no abc " $4;
            next;
        }
        print;
    } else {
        print;
    }
}

Mas daqui, parece que a única vez que algo especial é feito é quando !scnode é verdadeiro e /^abc disable/ corresponde, em todos os outros casos há apenas print . Então poderíamos combinar as condições com && (Claro que a separação entre diferentes tipos de arquivos não está mais tão clara.):

{
    if (!scnode && /^abc disable/) {
        print "no abc "$4"";
        next;
    } else {
        print;
    }
}

Como há um next que reduz a execução, o print final pode ficar sem a cláusula else e, na verdade, como todo o bloco de código é apenas if , poderíamos abandonar a condição para o nível principal e siga com uma ação padrão incondicional de impressão.

!scnode && /^abc disable/ {
    print "no abc "$4"";
    next;
}
1;

(Claro que isso pode parecer um pouco condensado agora.)

Além disso, no shell script, você não precisa incomodar os gatos, é melhor deixá-los dormindo e usar apenas o shell para redirecionamento. (E cite as variáveis do shell.)

 WhatFileIsIt < "$IN_FILE" > "$OUT_FILE"

O nome dessa função é um pouco confuso, realmente não responde a qualquer pergunta "o que", mas processa um arquivo. Talvez algo como ProcessFile ?

E bem, falando sobre funções, essa função usa a variável IN_FILE , que não é local para ela. Pode ser confuso se alguma vez precisar executar uma função para dois arquivos diferentes. Como o próprio shell script, a função também pode receber parâmetros, chamando MyFunction foo , faz com que $1 contenha foo dentro da função ..

Então, talvez eu faça algo como

ProcessFile() {
awk < "$1" -v filename="$1" '
[...]

(Não importa se você colocar o redirecionamento de entrada no meio ou no final da linha de comando do awk).

Use com:

ProcessFile "$IN_FILE" > "$OUT_FILE"
    
por 22.09.2016 / 20:09

Tags