AWK если условие

Вопрос или проблема

Дан файл input.txt с содержимым:

xyMnZnMs76XHgsWJ
size: YN3hxFqFeUxXUMrQ
USPqYEnbquwFhUW7
vhJJduHZu25qHzTw
size: JaTDhQYQtLRWBLjj
uE5HGDAZN6DHU73Q
QxVPfQQaKTgR9LXQ
grnsm8bwSz5fJbQS size:
7CcuZxCHSJYhcdqg
ZuWadAaLWFwDwj5Z

как использовать if (condition) {...} else {...}?

Я пытался использовать:

awk -F ':' '
IF ($1 ~ /size/) {
    print "match: "$0;
} ELSE {
    print "non-match: "$0;
}' input.txt

но все строки соответствуют (даже те, где $1 не содержит "size"):

match: xyMnZnMs76XHgsWJ
match: size: YN3hxFqFeUxXUMrQ
match: USPqYEnbquwFhUW7
match: vhJJduHZu25qHzTw
match: size: JaTDhQYQtLRWBLjj
match: uE5HGDAZN6DHU73Q
match: QxVPfQQaKTgR9LXQ
match: grnsm8bwSz5fJbQS size:
match: 7CcuZxCHSJYhcdqg
match: ZuWadAaLWFwDwj5Z

Я ожидаю, что вывод будет:

non-match: xyMnZnMs76XHgsWJ
match: size: YN3hxFqFeUxXUMrQ
non-match: USPqYEnbquwFhUW7
non-match: vhJJduHZu25qHzTw
match: size: JaTDhQYQtLRWBLjj
non-match: uE5HGDAZN6DHU73Q
non-match: QxVPfQQaKTgR9LXQ
non-match: grnsm8bwSz5fJbQS size:
non-match: 7CcuZxCHSJYhcdqg
non-match: ZuWadAaLWFwDwj5Z

Давайте объясним.

Синтаксическая структура для awk — это » pattern { action } «, где любой из компонентов (но не оба вместе) является необязательным. Когда вы написали IF ($1 ~ /size/) { print "match: "$0; }, вы не использовали ключевое слово if, а фактически конкатенировали пустую строку (неустановленную переменную IF) и выражение ($1 ~ /size/), которое оценивается либо в 0, либо в 1. Из-за конкатенации строк результат рассматривается как строка (“0” или “1“) и считается “истинным”, если она имеет ненулевую длину. Любой результат имеет длину, поэтому условие шаблона считается безусловно истинным. На этом этапе { action } запускается, и выполняется print "match: "$0.

Давайте исправим.

Изучив документацию для awk (см. man awk), вы обнаружите, что структура ifelse пишется в нижнем регистре. Более того, вы не можете использовать такую структуру за пределами » { action } « части каждого оператора.

awk -F: '
    { if ($1 ~ /size/) { print "match:", $0 } else { print "non-match:", $0 } }
' input.txt

Однако обратите внимание, что ваша строка grnsm8bwSz5fJbQS size: рассматривается как несоответствие в вашем требуемом выходе, но в этом коде выводится как соответствие. Это связано с тем, что регулярное выражение /size/ соответствует первому полю, разделенному двоеточиями, grnsm8bwSz5fJbQS size. Вам нужно было бы определить начало и конец строки для точного совпадения — но лучше сравнить как буквальную строку:

awk -F: '
    { if ($1 == "size") { print "match:", $0 } else { print "non-match:", $0 } }
' input.txt

Или,

awk -F: '
    $1 != "size" { print "non-match:", $0 }
    $1 == "size" { print "match:", $0 }
' input.txt

И даже,

awk -F: '
    $1 != "size" { printf "non-" }
    { print "match:", $0 }
' input.txt

Для этого я даже не использовал бы if-statement, они предназначены для более сложных вещей. Вы могли бы сделать просто так:

awk -F':' '/^size/ {print "match: " $0} !/^size/ {print "non-match: " $0}' input.txt

или мой предпочтительный способ заключается в использовании переменной, называемой pat, чтобы вы могли изменить её позже более легко:

awk -v pat="size" -F':'  '$1~pat {print "match: " $0}; $1!~pat {print "non-match: " $0}' input.txt

Это работает для меня:
awk -F: '{if ($1 =="size") {print "match: "$0} else {print "non-match: "$0}}'

С awk вы всегда должны использовать фигурные скобки для кода, например:

awk '{ ваш код }'

Также if/else пишется не заглавными буквами.
Вы можете найти дополнительные примеры здесь.

.

Ответ или решение

Когда мы говорим об использовании условия if в awk, важно понимать структуру и синтаксис этого мощного инструмента для обработки текстовых данных в Unix-подобных системах. Рассмотрим данный случай на примере файла input.txt со следующим содержимым:

xyMnZnMs76XHgsWJ
size: YN3hxFqFeUxXUMrQ
USPqYEnbquwFhUW7
vhJJduHZu25qHzTw
size: JaTDhQYQtLRWBLjj
uE5HGDAZN6DHU73Q
QxVPfQQaKTgR9LXQ
grnsm8bwSz5fJbQS size:
7CcuZxCHSJYhcdqg
ZuWadAaLWFwDwj5Z

Проблема заключалась в том, что неправильно использовалась конструкция if в awk, из-за чего все строки файла неправильно классифицировались как совпадающие. Рассмотрим, как можно использовать условие if корректно:

  1. Исправление ошибки: Изначально использовалась конструкция IF, которая неверна, так как в awk отсутствует поддержка заглавных букв для ключевых слов. awk чувствителен к регистру и следует использовать ключевые слова с маленькой буквы.

  2. Синтаксис awk: Для написания условий if и else в awk, необходимо помещать их внутрь блока действий {}. Вот исправленный пример:

    awk -F: '
    { if ($1 ~ /size/) { print "match:", $0 } else { print "non-match:", $0 } }
    ' input.txt
  3. Корректное использование регулярных выражений: Следует учитывать, что выражение $1 ~ /size/ будет находить совпадения в первых полях, содержащих текст size. Если нужно точно искать строки, начинающиеся с size, лучше использовать оператор сравнения ==:

    awk -F: '
    { if ($1 == "size") { print "match:", $0 } else { print "non-match:", $0 } }
    ' input.txt
  4. Упрощение без if-conditions: В данном случае, использование условия можно упростить, воспользовавшись следующей конструкцией:

    awk -F':' '/^size/ {print "match:", $0} !/^size/ {print "non-match:", $0}' input.txt
  5. Использование переменных для гибкости: Чтобы ваша программа была более адаптируема, можно ввести переменную pat, что упростит возможные изменения:

    awk -v pat="size" -F':'  '$1 ~ pat { print "match:", $0 } $1 !~ pat { print "non-match:", $0 }' input.txt

Этот подход более точно удовлетворит ваши цели и улучшит читаемость кода. Если у вас возникнут дополнительные вопросы касательно обработки файлов с использованием awk, рассмотрите углубленное изучение документации и практических примеров.

Оцените материал
Добавить комментарий

Капча загружается...