Почему хранение моего регулярного выражения в переменной нарушает тест сравнения? (Awk / Gawk) - PullRequest
1 голос
/ 17 апреля 2019

У меня есть файл с именем regeces, содержащий ряд построчных регулярных выражений. Вот пример:

The .* is .* years old
I like .* with lots of .*

У меня также есть очень креативный файл данных, который называется data:

The car is 3 years old
I like pizza with lots of pepperoni
I like tacos with lots of cheese
The house is 10 years old
A non-matching line
The couch is 5 years old
I like customers with lots of money
This line does not match

Хотя регулярные выражения, конечно, написаны не так узко, их достаточно, чтобы они соответствовали всем, кроме пятой и последней строкам data, и объясняли мою проблему. Теперь вот моя программа:

#!/usr/bin/awk -f

BEGIN {
        while ("cat regeces" | getline)
                {
                reg = "/" $0 "/||" reg
                }
    sub(/\|\|$/, "", reg)
    print reg
    }

# $0 ~ /I like .* with lots of .* /||/The .* is .* years old/ {
$0 ~ reg {
    print $0
    }

Итак, в разделе BEGIN он читает regeces, создает одно регулярное выражение и сохраняет его в переменной. В качестве средства устранения неполадок он также распечатывает его. В теле он сравнивает каждую строку с регулярным выражением, сохраненным в переменной. Закомментированная строка для удобства тестирования проблемы.

Регулярное выражение, хранящееся в reg:

/I like .* with lots of .* /||/The .* is .* years old/

Теперь, если я запускаю программу как написано, она выводит каждую строку; то есть он не исключает пятую и последнюю строки data. Однако, если я возьму приведенное выше регулярное выражение и заменим сравнительный тест программы:

$0 ~ /I like .* with lots of .* /||/The .* is .* years old/

работает отлично! Таким образом, регулярное выражение выглядит вполне нормально, но по какой-то причине поместить его в переменную и проверить его не удается. Это почему? Что бы это исправить? Очевидно, что регулярные выражения могут быть сохранены в переменных, но в чем проблема с этим?

1 Ответ

3 голосов
/ 17 апреля 2019

Вы добавляете буквенные косые черты к регулярному выражению, поэтому требуется, чтобы сопоставленный текст содержал косые черты вокруг него.

Косые черты используются в синтаксисе самого Awk вокруг регулярных выражений; но эти регулярные выражения, которые вы пытаетесь сопоставить, являются просто строками. Для сравнения:

awk 'BEGIN { var = "^hello$" }
    $0 ~ var
    /^hello$/' <<<$'hello\ngoodbye'

напечатает hello дважды, потому что два совпадения эквивалентны.

Вот значительно переработанная версия вашего скрипта:

awk 'NR==FNR { r = (NR>1 ? r "|" : "") $0; next }
    $0 ~ r' regeces data

Это просто переопределяет grep, но должно быть легко увидеть, как изменить или расширить его, чтобы сделать больше или разные вещи.

Обратите внимание, как мы используем один | для чередования внутри одного регулярного выражения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...