Awk: if и условный оператор в одном блоке

Awk: if и условный оператор в одном блоке

Вот код скрипта, в котором я должен проверить имя файла на «pretempsc.cfg» и вывести его содержимое как есть. Для любого другого файла мне следует изменить только строки, начинающиеся с «abc disable ...» на «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

При выполнении этого скрипта возникает следующая ошибка:

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

Из того, что мне удалось найти, я подозреваю, что я неправильно использую if и condition-action в блоке действия, но я не могу понять, в чем именно ошибка.

Примечание: Я ДОЛЖЕН использовать awk в скрипте оболочки, и есть много других функций, похожих на WhatFileIsIt, которые выполняют собственную обработку IN_FILE.

решение1

Да, вам нужно изменить это сопоставление с образцом на полное ifвыражение:

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

( /pattern/— это сокращение от $0 ~ /pattern/, где $0содержит всю входную строку.)

Обратите внимание, что printтам печатается только четвертый столбец ввода после no abc, поэтому abc disable foo bar dooпревращается просто в no abc bar. Я не уверен, что это то, что вы хотели.


Пока мы этим занимаемся, на ум приходят и другие вещи... Можете смело игнорировать все это, если это слишком очевидно или противоречит остальной части вашего сценария. (И будем надеяться, что я не допустил слишком много ошибок.)

Мне кажется, в конце есть лишняя правая скобка print, и отступ самого глубокого условия немного смещен, поэтому немного перепишу:

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

Но отсюда, похоже, что что-то особенное происходит только тогда, когда и то, и другое !scnodeверно и /^abc disable/совпадает, во всех остальных случаях есть только print. Поэтому мы могли бы объединить условия с &&(конечно, разделение между различными типами файлов уже не такое четкое.):

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

Поскольку есть , nextкоторый сокращает выполнение, финал printможет быть оставлен без elseпредложения, и фактически, поскольку весь блок кода представляет собой просто if, мы могли бы опустить условие на основной уровень и продолжить его безусловным действием по умолчанию — печатью.

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

(Конечно, сейчас это может выглядеть слишком сжато.)


Кроме того, в скрипте оболочки вам не нужно беспокоить кошек, лучше оставьте их спать и используйте только оболочку для перенаправления. (И заключите переменные оболочки в кавычки.)

 WhatFileIsIt < "$IN_FILE" > "$OUT_FILE"

Название этой функции немного сбивает с толку, она не отвечает на вопросы "что", а обрабатывает файл. Может быть, что-то вроде ProcessFile?

И, что касается функций, то эта функция использует переменную IN_FILE, которая не является локальной для нее. Может сбивать с толку, если когда-либо понадобится запустить функцию для двух разных файлов. Как и сам скрипт оболочки, функция также может принимать параметры, вызывая MyFunction foo, делает ее $1содержащей fooвнутри функции..

Так что я бы, наверное, сделал что-то вроде

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

(Не имеет значения, поместите ли вы перенаправление ввода в середину или в конец командной строки awk.)

Использовать с:

ProcessFile "$IN_FILE" > "$OUT_FILE"

Связанный контент