Вопрос или проблема
Эту функцию выделения можно легко выполнить в grep
с --color
. Но grep
не может выполнять обычное и обратное сопоставление одновременно, например grep foo -v bar ...
(мне нужна эта функция, так как --color
может быть использован только на начальном входе в pipe |
, поэтому следующий grep будет использовать эти выделенные результаты, что делает grep foo --color=always ... | grep -v "foo bar"
не удаляющим те строки с “foo bar”).
Поэтому я использовал awk
, как указано в вышеприведенной ссылке, но он лишен функции выделения. Мы можем извлечь результаты выражения с помощью match
и substr
, где мы оборачиваем шаблон regex в match
, например /\<no issue\>/
. Затем мы можем выделить только результат regex при помощи ANSI кодов цвета с помощью printf substr($0,1,RSTART-1) "\033[1;31m" substr($0,RSTART,RLENGTH) "\033[0m: " substr($0,RSTART+RLENGTH) "\n"
.
Вопрос:
Но match
не работает для логического выражения /\<no issue\>/ || !/\<issue\>/
, построенного с помощью regex выражений, как указано в ссылке. Есть ли одно изящное решение (возможно, с другими инструментами)?
Я подумал об одном временном решении /\<no issue\>/ || !/\<issue\>/{match($0,/\<no issue\>/); printf ...}
, но это будет выполнять regex дважды.
Ответ или решение
Конечно, обсудим, как можно подсветить совпадения с регулярным выражением в awk
, когда используется комбинация из нескольких регулярных выражений с помощью оператора ||
, который означает логическое "ИЛИ".
Контекст и Проблема
С тех пор как grep
предоставляет опцию --color
для подсветки результата, существует ограничение: grep
не может одновременно выполнять обычные и обратные совпадения. Например, если вы попытаетесь использовать команду grep foo --color=always ... | grep -v "foo bar"
, grep
не сможет исключить строки с "foo bar", поскольку --color
работает только на начальном вводе в конвейере.
Ваша цель — использовать awk
для такого извлечения и подсветки паттернов. И хотя в awk
можно воспользоваться функциями match
и substr
, они ограничены при работе с логическими выражениями вроде /\<no issue\>/ || !/\<issue\>/
.
Решение на основе awk
-
Подготовка регулярных выражений: Изначально необходимо подготовить регулярные выражения, которые вы хотите использовать для поиска. Важно точно определить, какие части текста вы хотите выделить.
-
Использование
match
иsubstr
вawk
: Основная проблема состоит в невозможности примененияmatch
к выражению||
. Однако вы можете сначала использовать логику условий для выполнения определенных действий, после чего отдельно оформить подсветку. -
Оптимизация производительности: Ваш временный обходной путь использования
match
дважды действительно менее эффективен, но есть стратегия, которая поможет:awk '{ if (/\<no issue\>/ || !/\<issue\>/) { exp = /\\<no issue\\>/ if (match($0, exp)) { printf substr($0,1,RSTART-1) "\033[1;31m" substr($0,RSTART,RLENGTH) "\033[0m" substr($0,RSTART+RLENGTH) "\n" } } }'
В этом скрипте
awk
сначала определяется условие для вывода на основе логического выражения, после чего отдельно происходит поиск и подсветка. -
Подумайте о других инструментах: Если вы ищете более "элегантное" решение, специально разработанное для работы со сложными регулярными выражениями и требующее словесной обработки, возможно, стоит рассмотреть использование других специализированных инструментов, таких как
perl
, который поддерживает расширенные возможности работы с регулярными выражениями и цветовой вывод:perl -pe 's/(pattern1|pattern2)/\e[1;31m$1\e[0m/g'
Заключение
Использование awk
для работы с регулярными выражениями требует более сложного подхода при комбинировании нескольких условий. Вместо этого, можно использовать более продвинутые инструментальные средства, предоставляющие расширенные возможности работы с текстом и поддержкой ANSI-цветов. Надеюсь, это предложение поможет вам справиться с задачей подсветки паттернов внутри awk
и выбрать подходящий инструмент для ваших нужд.