2016-05-30 2 views
1

У меня есть текстовый файл, например так:Bash - отключить регулярное выражение в AWK заявлении

tets v1.0 
psutil==4.1.0 
tclclean==2.4.3 

test v2.0 
psutil==3.1.1 
pyYAML==3.11 

not_test 
psutil==4.1.0 
tclclean==2.8.0 

и я использую AWK и ввод пользователя, чтобы найти текст в первой строке конкретного блока. Команда, которую я использую (где user_in является ввод пользователя) ...

awk -v ORS='\n\n' -v RS= -v FS='\n' "\$1 ~ \"^$user_in$\"" myfile.txt

Проблема заключается в том, что если пользователь вводит «*», оператор AWK собирается принять его как регулярное выражение и дайте мне все три блока, но я не хочу, чтобы что-то выводилось, так как оно не соответствует буквальным буквам.

Что я пытаюсь сказать, есть способ отключить регулярное выражение в awk и взять каждый символ в буквальном ключе (так же, как fgrep)?

ответ

3

Читать книгу Эффективное Awk программирование, 4-е издание, Арнольд Роббинс.

Теперь давайте очистить ваш скрипт:

awk -v ORS='\n\n' -v RS= -v FS='\n' "\$1 ~ \"^$user_in$\"" myfile.txt 

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

awk -v ORS='\n\n' -v RS= -v FS='\n' -v user_in="$user_in" '$1 ~ "^"user_in"$"' myfile.txt 

И если вы хотите проверить строку, то просто проверить строку, а не регулярных выражений, например найти записи, где $ 1 НАЧИНАЮТСЯ С вашей целевой строкой:

awk -v ORS='\n\n' -v RS= -v FS='\n' -v user_in="$user_in" 'index($1,user_in)==1' myfile.txt 

или СОДЕРЖИТ вашу целевую строку:

awk -v ORS='\n\n' -v RS= -v FS='\n' -v user_in="$user_in" 'index($1,user_in)>=1' myfile.txt 

или концов с вашей целевой строкой:

awk -v ORS='\n\n' -v RS= -v FS='\n' -v user_in="$user_in" 'index($1,user_in)==(length($1)-length(user_in))' myfile.txt 

или если вы хотите найти случаи, когда $ 1 IS целевая строка, а не только начиная с него (как ваш скрипт пытается), это еще проще:

awk -v ORS='\n\n' -v RS= -v FS='\n' -v user_in="$user_in" '$1 == user_in' myfile.txt 
+0

Я был на самом деле ищет для случая, когда $ 1 является строкой, ничего больше не меньше. Я бы хотел, чтобы было возможно обратное сбрасывание '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' было бы похоже на '$ 1 ==" \^$ user_in \ $ "', но оно, похоже, не работает. Но ваш код работает отлично! – TheGirrafish

+0

Каждый раз, когда вы пытаетесь отключить все метасимволы регулярного выражения в любом инструменте, у вас неправильный подход, поскольку вы действительно хотите просто выполнить строку, а не регулярное выражение, сравнение.Рад, что он работает на вас. –

2

~ - оператор регулярного выражения. Если вы не хотите использовать регулярные выражения, а затем использовать == и не заворачивайте вход в ^...$, как это:

awk -v ORS='\n\n' -v RS= -v FS='\n' "\$1 == \"$user_in\"" myfile.txt 

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

awk -v ORS='\n\n' -v RS= -v FS='\n' -v user_in="$user_in" '$1 == user_in' 
Смежные вопросы