awk рассматривает переменную как литерал в регулярном выражении - PullRequest
0 голосов
/ 30 октября 2018

Я хотел бы передать пару переменных оболочки в команду awk, которая затем использует регулярные выражения для сопоставления их в поле. Однако я хочу, чтобы содержимое переменных обрабатывалось как литералы в регулярном выражении. Все это делается для каждой строки входного файла.

Итак, это

123^A

будет найден в любом из этих

123^A|field2|field3
123^A~000^A|field2|field3
000^A~123^A|field2|field3
000^A~123^A~999^A|field2|field3

Но ни один из них

123^B|field2|field3
1234^A|field2|field3
123|field2|field3
123~000|field2|field3

Пример, который не работает:

read inputfile?'Enter the input file: '
read tackedonvalue?'Enter the value to tack onto each input value: '
read searchfile?'Enter the search file: '
read fieldnum?'Enter the field number to search: '
read delim?'Enter the field delimiter: '

while read -r SEARCHTERM
do awk -F"${delim}" -v a="(^|~)${SEARCHTERM}${tackedonvalue}(~|$)" -v COL="${fieldnum}" '$COL ~ /a/' ${searchfile} >> output_file.txt
done < ${inputfile}
  • "123" будет строкой из переменной $inputfile из ввода
  • «^ A» будет переменной $tackedonvalue из входных данных

Что делает этот пример неработающим, так это то, что переменная $tackedonvalue часто содержит ^ символов, которые затем необходимо экранировать для регулярного выражения. (Экранировать их вручную во входных данных нельзя). В эту переменную также могут быть введены другие специальные символы, которые также необходимо экранировать, поэтому я не хочу искать / заменять каждый специальный символ для каждого случая.

Еще один пример, который я попробовал первым, но не смог приступить к работе (те же подсказки ввода и while read, что и раньше):

awk -F"${delim}" -v a="${SEARCHTERM}" -v b="${tackedonvalue}" -v COL="$fieldnum" '$COL ~ ("(^|~)" a b "(~|$)")' ${searchfile} >> output_file.txt

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

Если бы якоря могли быть исправлены для этого второго примера И содержимое переменной было бы обработано как литералы, то это был бы другой маршрут.

P.S. - Первый пост, дайте мне знать, что изменить / улучшить / предоставить.

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Я не знаю про awk, но это легко сделать с помощью perl:

$ cat a.txt
123^A|field2|field3
123^A~000^A|field2|field3
000^A~123^A|field2|field3
000^A~123^A~999^A|field2|field3
123^B|field2|field3
1234^A|field2|field3
123|field2|field3
123~000|field2|field3
$ export PAT=123^A
$ export FIELDNUM=0
$ perl  -F'\|' -le "print if \$F[${FIELDNUM}] =~ /(^|~)\Q${PAT}\E(~|$)/" a.txt
123^A|field2|field3
123^A~000^A|field2|field3
000^A~123^A|field2|field3
000^A~123^A~999^A|field2|field3

В регулярном выражении между \Q и \E метасимволы автоматически экранируются / игнорируются.

0 голосов
/ 30 октября 2018

Вам нужно экранировать ^ в поисковом запросе, поскольку он имеет особое значение в регулярных выражениях.

SEARCHTERM=${SEARCHTERM//^/\\^}

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

awk -v -F"$delim" search="$SEARCHTERM" -v tacked="$tackedonvalue" -v col="$fieldnum" '
    BEGIN {gsub(/[]*^$]/, "\\&", search); pattern = "(^|~)" search tacked "(~|$)" }
    $col ~ pattern' "$searchfile"

Кстати, вы не должны использовать все прописные переменные оболочки. Соглашение состоит в том, что эти имена зарезервированы для переменных среды.

Но, возможно, вам вообще не следует использовать сопоставление с образцом. Я думаю, что вы можете просто разбить поле на символе ~, а затем выполнить цикл для проверки этого массива, если какой-либо из элементов соответствует строке поиска.

split($col, array, "~");
for (i in array) if (array[i] == (search tacked)) { print; break }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...