Awk: if y declaración condicional en el mismo bloque

Awk: if y declaración condicional en el mismo bloque

Aquí está el código de un script en el que debo verificar que el nombre del archivo sea 'pretempsc.cfg' e imprimir su contenido tal como está. . Para cualquier otro archivo, solo debo modificar las líneas que comienzan con 'abc enable...' a 'no abc...'.

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

Al ejecutar este script, aparece el siguiente error:

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

Por lo que pude buscar, sospecho que me equivoco en el uso de if y condition-action dentro del bloque de acción, pero no puedo determinar qué está mal exactamente.

Para tener en cuenta: DEBO usar awk dentro del script de shell, y hay muchas otras funciones similares a WhatFileIsIt que realizan su propio procesamiento en IN_FILE.

Respuesta1

Sí, necesitas cambiar esa coincidencia de patrón a una ifdeclaración completa:

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

( /pattern/es una abreviatura de $0 ~ /pattern/, donde $0contiene toda la línea de entrada).

Tenga en cuenta que printallí imprime solo la cuarta columna de la entrada después de no abc, por lo que abc disable foo bar doose convierte en solo no abc bar. No estoy seguro de si esto es lo que querías.


Mientras estamos en esto, me vienen a la mente algunas otras cosas... Siéntete libre de ignorar todo esto, si es demasiado obvio o entra en conflicto con el resto de tu guión. (Y esperemos no haber cometido demasiados errores).

Creo que hay una llave extra a la derecha al final de print, y parece que la sangría de la condición más profunda está un poco fuera de lugar, así que reescribo un poco:

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

Pero a partir de aquí, parece que el único momento en que se hace algo especial es cuando ambos !scnodeson verdaderos y /^abc disable/coinciden; en todos los demás casos solo existe el print. Entonces podríamos combinar las condiciones con &&(Por supuesto, la separación entre diferentes tipos de archivos ya no es tan clara):

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

Dado que hay un nextque acorta la ejecución, el final printpuede permanecer sin la elsecláusula y, de hecho, dado que todo el bloque de código es solo un if, podríamos eliminar la condición al nivel principal y continuar con una acción predeterminada incondicional de impresión.

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

(Por supuesto, esto puede parecer demasiado condensado ahora).


Además, en el script de shell, no es necesario molestar a los gatos, es mejor dejarlos durmiendo y usar solo el shell para la redirección. (Y cite las variables del shell).

 WhatFileIsIt < "$IN_FILE" > "$OUT_FILE"

El nombre de esa función es un poco confuso, en realidad no responde ninguna pregunta de "qué", sino que procesa un archivo. ¿Quizás algo así como ProcessFile?

Y bueno, hablando de funciones, esa función usa la variable IN_FILE, que no es local para ella. Puede resultar confuso si alguna vez es necesario ejecutar una función para dos archivos diferentes. Al igual que el script de shell en sí, la función también puede tomar parámetros, llamarlos MyFunction fooy $1contenerlos foodentro de la función.

Así que tal vez haría algo como

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

(No importa si coloca la redirección de entrada en el medio o al final de la línea de comando awk).

Usar con:

ProcessFile "$IN_FILE" > "$OUT_FILE"

información relacionada