
Вот код скрипта, в котором я должен проверить имя файла на «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"