Обработка метасимволов в строках поиска

У меня есть пользовательский ввод, который будет использоваться в строке поиска, которая может содержать метасимвол

Например, С# или С++

моя команда grep в функции была:

grep -E "$1|$2" test.txt

при прямой замене:

grep -E "C\+\+|testWord" test.txt
grep -E "C\#|testWord" test.txt

первый хорошо поймал линии, но не второй. Как ни странно, # был полностью проигнорирован. Без прямой замены оба перехватывают что-либо с помощью c, за которым следует testWord вместо c++ и c# соответственно.

Я пытался справиться с этим, используя sed

$temp = `echo $1 | sed 's/[\#\!\&\;\`\"\'\|\*\?\~\<\>\^\(\)\[\]\{\}\$\+\\]/\\&/g'`

но это не работает правильно. Или есть другой способ обработки пользовательского ввода с помощью метасимволов?

заранее спасибо


person eruina    schedule 25.01.2010    source источник
comment
Как вы получаете пользовательский ввод? В качестве аргументов командной строки или через команду read?   -  person Dennis Williamson    schedule 26.01.2010
comment
Интересно. Используя ваши новые примеры, C++ - это тот, который доставляет мне проблемы, когда кажется, что C# проблематичен для вас. Я обнаружил, что помогает использование как кавычек, так и обратной косой черты: grep -E "C\+\+", как и использование обычного grep с экранированной последовательностью без экранирования плюсов: grep "C++\|C#"   -  person Dennis Williamson    schedule 26.01.2010
comment
Что касается вашего примера sed, вам обычно не нужен знак доллара в имени переменной в левой части присваивания (если вы не делаете косвенное обращение).   -  person Dennis Williamson    schedule 26.01.2010
comment
две переменные должны быть в одной строке, чтобы их можно было найти, и в этой последовательности сначала $1, затем $2, кто-то указал, что awk может работать, думаю, я пойду прочитаю об этом. Надеюсь, это правильный путь, кстати, спасибо за помощь :)   -  person eruina    schedule 26.01.2010


Ответы (3)


если вы передаете ввод в качестве аргументов скрипту

#!/bin/bash

input1="$1"
input2="$2"
while read -r line
do
    case "$line" in
        *$input1*|*$input2* ) echo "found: $line";;
    esac
done  <"BooksDB.txt

"

выход

$ cat file
this is  a line
this line has C++ and C#
this line has only C++ and that's it
this line has only C# and that's it
this is end line Caa

$ ./shell.sh C++ C#
found: this line has C++ and C#
found: this line has only C++ and that's it
found: this line has only C# and that's it

если вы получаете ввод от чтения

read -p "Enter input1:" input1
read -p "Enter input2:" input2
while read -r line
do
    case "$line" in
        *$input1|*$input2* ) echo "found: $line";;
    esac
done <"BooksDB.txt"
person ghostdog74    schedule 26.01.2010
comment
Я пробовал использовать две переменные со следующим кодом: fileContents = cat BookDB.txt; case $1*$2 в fileContents ) найдено эхо!;; esac вообще ничего не нашел. Я передавал входные данные в качестве аргументов сценарию. Извините, я не знаю, как форматировать код в комментариях. Выглядит довольно неряшливо.. ›.‹ - person eruina; 26.01.2010
comment
см. новое редактирование. кот не нужен. просто выполните цикл чтения, используя оболочку. - person ghostdog74; 26.01.2010

Это работает для меня:

$ testfun1(){ echo "foo $1" | grep "$1"; }
$ testfun1 C#
foo C#
$ testfun2(){ read a; echo "bar $a" | grep "$a"; }
$ testfun2
C#
bar C#

Изменить:

Вы можете попробовать эту форму без -E:

$ testfun3(){ grep "$1\|$2" test.txt; }
$ testfun3 C++ awk
something about C++
blah awk blah
$ testfun3 C# sed
blah sed blah
the text containing C#
$ testfun3 C# C++
something about C++
the text containing C#
person Dennis Williamson    schedule 25.01.2010
comment
Это работает, но не с двумя переменными. Я понял, что мой оператор grep был неправильным. Теперь это исправлено, но по-прежнему не может обрабатывать строки с метасимволами :( - person eruina; 26.01.2010

Просто укажите все метасимволы grep в $1 и $2, прежде чем добавлять их в выражение grep.

Что-то вроде этого:

quoted1=`echo "$1" | sed -e 's/\([]\.?^${}+*[]\)/\\\\\1/g'`
quoted2=`echo "$2" | sed -e 's/\([]\.?^${}+*[]\)/\\\\\1/g'`
grep -E "$quoted1\|$quoted2" test.txt

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

person GaryO    schedule 26.01.2010
comment
я заметил два [] в заключенных \( и \), какова цель добавления второго? и в строке замены я понял только цель 3 \, 2, чтобы сделать первую обратную косую черту, которая будет добавлена ​​​​спереди, последнюю для представления \ 1. для чего нужны последние два? - person eruina; 27.01.2010