Действительно ли возможно сделать grep с ключевыми словами, сохраненными в массиве?

Действительно ли возможно сделать grep с ключевыми словами, сохраненными в массиве.

Вот возможный фрагмент кода... Исправьте его

args=("key1" "key2" "key3")

cat file_name |while read line
 echo $line | grep -q -w ${args[c]}
done

В данный момент я могу искать только одно ключевое слово. Я хотел бы искать все ключевые слова, который хранится в массиве args.

Любое предложение высоко ценилось бы.

Спасибо, Kiran

8
задан P Shved 19 February 2010 в 10:11
поделиться

5 ответов

args=("key1" "key2" "key3")
pat=$(echo ${args[@]}|tr " " "|")
grep -Eow "$pat" file

Или с помощью shell

args=("key1" "key2" "key3")
while read -r line
do
    for i in ${args[@]}
    do
        case "$line" in
            *"$i"*) echo "found: $line";;
        esac
    done
done <"file"
9
ответ дан 5 December 2019 в 10:02
поделиться

Команда

( IFS="|" ; grep --perl-regexp "${args[*]}" ) <file_name

ищет в файле каждое ключевое слово в массиве. Она делает это путем построения регулярного выражения word1|word2|word3, которое соответствует любому слову из приведенных альтернатив (в режиме perl).

Если бы существовал способ объединить элементы массива в строку, разделив их последовательностью символов (а именно, \|), это можно было бы сделать без perl regexp.

1
ответ дан 5 December 2019 в 10:02
поделиться

возможно что-то вроде этого;

cat file_name |while read line
for arg in ${args[@]}
do
echo $line | grep -q -w $arg}
done
done

не проверено!

0
ответ дан 5 December 2019 в 10:02
поделиться

Вы можете использовать некоторую магию расширения bash для префиксации каждого элемента с -e и передачи каждого элемента массива как отдельного шаблона. Это поможет избежать некоторых проблем с прецедентом, когда ваши шаблоны могут плохо взаимодействовать с оператором |:

$ grep ${args[@]/#/-e } file_name

Недостатком этого способа является то, что вы не можете использовать пробелы в ваших шаблонах, потому что это разделит аргументы grep. Нельзя ставить кавычки вокруг вышеприведенного расширения, иначе вы получите "-e pattern" как один аргумент для grep.

4
ответ дан 5 December 2019 в 10:02
поделиться

Это однострочный:

args=("key1" "key2" "key3")
keys=${args[@]/%/\\|}      # result: key1\| key2\| key3\|
keys=${keys// }            # result: key1\|key2\|key3\|
grep "${keys}" file_name 

Редактировать:

На основе предложения Павла Шведа :

( IFS="|"; keys="${args[*]}"; keys="${keys//|/\\|}"; grep "${keys}" file_name )

Первая версия как однострочная:

keys=${args[@]/%/\\|}; keys=${keys// }; grep "${keys}" file_name

Edit2:

Еще лучше чем версия, использующая IFS :

printf -v keys "%s\\|" "${args[@]}"; grep "${keys}" file_name
3
ответ дан 5 December 2019 в 10:02
поделиться