использование awk для поиска специальных символов в текстовом файле - PullRequest
1 голос
/ 27 апреля 2020

Мне нужно отсканировать файл с множеством различных специальных символов и значений. Учитывая набор специальных символов - мне нужно указать значение рядом с ним:

547 %$ 
236 \"
4523 &* 
8876 (*
8756 "/
...

Я использую команду awk с gsub, чтобы найти последовательности как они есть.

awk -v st="$match_string" 'BEGIN {gsub(/(\[|\]|\-|\$|\*|\:|\+|\"|\(|\))/,"\\\\&", st)} match($0,st) {print;exit}' file.txt

Команда отлично работает, например,

> (*
>> 8876 (*

Однако у меня возникают проблемы с использованием команды для поиска последовательности \ "Я пытаюсь добавить в gsub различные строки, чтобы представить последовательность:

|\\|
|\\\\|
|\\\\"|
...

Но результат всегда:

> \"
>> 8756 "/

, в то время как результат, который я ищу, может быть:

> \"
>> 236 \"

Кажется, что gsub не работает, и \ "интерпретируется так же, как" Любые идеи?

. Это короткий скрипт для запуска - - он должен найти символ, присоединенный к значению в first_num - Далее он должен напечатать первое значение в файле, связанном с Обнаружен символ

first_num=$1
echo "looking for : $first_num"
sym_to_check=$(awk -v s="$first_num"  '$0~s {if ($0~s)print $2}' temp.txt)
echo "symbol - $sym_to_check"
first_val=$(awk -v s="$sym_to_check" 'BEGIN {gsub(/(\[|\]|\-|\$|\^|\*|\:|\+|\"|\(|\))/,"\\\\&",s)} $0~s {if ($0~s)print; if ($0~s)exit}' temp.txt)
echo "first val- $first_val"

Предположим, что txt-файл:

547 %$ 
111 [*
222 ()
5655 (*
454 )"
35 #!
743 \"
657 #!
236 \"
4523 &* 
8876 (*
456 \"
8756 "/

Первый запуск в порядке:

> bash temp1.sh 8876
    looking for : 8876
    symbol - (*
    first val- 5655 (*

скрипт находит первое значение, прикрепленное к (* но следующий прогон плох:

> bash temp1.sh 236
looking for : 236
symbol - \"
first val- 454 )"

символ кор rect - ищет \ ", но при поиске первого значения, прикрепленного к нему, он ищет первый символ с" Это дает значение 454) "вместо желаемых 743 \"

1 Ответ

0 голосов
/ 27 апреля 2020

То, как вы инициализируете переменную awk st с использованием -v st="$match_string", заключается в разработке расширения escape-последовательностей (поэтому \t в "$match_string" станет буквальным символом табуляции в st, например), и вы вы используете оператор регулярного выражения match(), но пытаетесь избежать метасхем регулярного выражения, чтобы заставить его действовать так, как будто он выполняет строку вместо сопоставления с регулярным выражением, а затем выполняется частичное сопоставление всей строки (например, $0~85 будет соответствовать 1853) вместо полного сопоставления в указанном c поле ($1==85).

Вот как вы запускаете переменные awk из оболочки без интерпретации escape-последовательностей, а затем проверяете их как полностью совпадающие буквенные строки или числа в указанном c поле, а не частичное совпадение регулярных выражений по всей строке:

$ match_string='\"'

$ st="$match_string" awk 'BEGIN{st=ENVIRON["st"]} $2==st{print; exit}' file
743 \"

$ awk 'BEGIN{st=ARGV[1]; ARGV[1]=""} $2==st{print; exit}' "$match_string" file
743 \"

$ awk 'BEGIN{st=ARGV[1]; ARGV[1]=""} $1==st{print; exit}' '743' file
743 \"

Не все awks поддерживают ENVIRON[], поэтому первый подход не будет работать во всех awks, но второй will.

См. Как использовать переменные оболочки в сценарии awk? , как установить переменные awk из оболочки и когда вы хотите выполнить литерал st. В случае кольцевых сравнений обычно проще просто использовать строковые операторы, такие как == и index(), вместо использования операторов регулярных выражений, таких как ~ или match(), и пытаться экранировать все метасимволы регулярных выражений, чтобы заставить их действовать как строки.

Если вы когда-либо ДЕЙСТВИТЕЛЬНО хотели экранировать все метасхемы регулярных выражений, то синтаксис для этого будет:

gsub(/[^^]/,"[&]",st); gsub(/\^/,"\\^",st)

, а не то, что есть в коде в вашем вопросе:

gsub(/(\[|\]|\-|\$|\*|\:|\+|\"|\(|\))/,"\\\\&", st)

См. Можно ли надежно избежать метасимволов регулярных выражений с помощью sed , чтобы объяснить, почему это правильный синтаксис.

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