2016-06-22 2 views
1

У меня есть этот скрипт, где я прошу 4 шаблона, а затем используйте их в команде grep. То есть, я хочу посмотреть, соответствует ли строка любому шаблону.Передача пустых строк команде grep

echo -n "Enter pattern1" 
read pat1 
echo -n "Enter pattern2" 
read pat2 
echo -n "Enter pattern3" 
read pat3 
echo -n "Enter pattern4" 
read pat4 

cat somefile.txt | grep $pat1 | grep $pat2 | grep $pat3 | grep $pat4 

Проблема я бегу в том, что если пользователь не предоставляет один из шаблонов (которые я хочу, чтобы) команда Grep не работает.

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

+0

@fedorqu - Я извиняюсь за вопрос дубликата вопрос. Если к настоящему времени это не больно очевидно, я очень к этому отношусь. – berserker

+0

@berserker вы хотите фильтровать с помощью AND или OR? трафик grep на другой grep будет фильтровать первые результаты. Обратите внимание, что если вы скажете: 'pat = $ {pat: -" "}' заменит пустой контент на '' '', а затем 'grep '$ pat' 'он работает, так как' grep' 'file' просто возвращает полный контент , – fedorqui

+0

@fedorqu - Я хочу фильтровать по OR. В основном, я занимаюсь поиском syslog и принимаю ввод для src и dst ip, а также src и dst-порт. Я хочу, чтобы мой поиск работал либо с четырьмя входами, либо с одним из них. – berserker

ответ

3

Ваш код имеет много проблем:

  • код дублирования
  • Interactive просящие потенциально неиспользованной информации
  • с использованием echo -n не является портативным
  • бесполезно использование кошки

Здесь это то, что я написал, что ближе к тому, что вы должны использовать вместо:

i=1 
printf %s "Enter pattern $i: " 
read -r input 
while [[ $input ]]; do 
    pattern+=(-e "$input") 
    let i++ 
    printf %s "Enter pattern $i (Enter or Ctrl+D to stop entering patterns): " 
    read -r input 
done 
echo 
grep "${pattern[@]}" somefile.txt 

EDIT: Это не ответил на вопрос OP, этот поиск для нескольких моделей с OR вместо AND ...

Здесь рабочий AND решение (это остановит запрашивая узоры на первый пустой один или после 4-ого):

pattern= 
for i in {1..4}; do 
    printf %s "Enter pattern $i: " 
    read -r input 
    [[ $input ]] || break 
    pattern="${pattern:+"$pattern && "}/${input//\//\\/}/" 
done 
echo # skip a line 
awk "$pattern" somefile.txt 

Вот некоторые ссылки, из которых вы можете узнать, как программировать на баш:

+0

Обратите внимание, что вы также можете использовать цикл синтаксиса C и сказать 'for ((i = 1; i <= 5; i ++)); делать ...; done', вместо использования 'let' (отметьте [Как добавить номера в сценарий bash] (http://stackoverflow.com/a/6348941/1983854)). +1 для трюка массива. Обратите внимание, что вы можете указать 'input = $ {input: -" "}' для случая, когда ввод не задан. – fedorqui