Вложенный конвейерный grep приводит к строке «(стандартный ввод)» [дубликат]

если в этом пакете есть двоичный файл, который можно найти, вы можете сделать -

package_name=<packge-name>
t=`which $package_name`
[ -z "$t" ] && echo "the $package_name isn't installed!"
6
20.04.2017, 15:14
5 ответов

используйте "вырезать" для удаления строк после ":", тогда вы получите части файла (при условии, что пути к файлам не содержат двоеточие или символы новой строки и не соответствуют второму выкройки сами).

grep -ir "Some string" . |grep "Another string I want to find in the other grep's results" | cut -d ":" -f 1

в случае дублирования используйте "uniq"

grep -ir "string1" . | grep "string2" | cut -d: -f1 | uniq
5
27.01.2020, 20:20

Опция -lкоманды grepзаставит утилиту печатать только имя файла, содержащего указанный шаблон. В мануале по моей системе об этой опции сказано следующее:

В файл записываются только имена файлов, содержащих выбранные строки. стандартный вывод. grep будет искать файл только до тех пор, пока не будет найдено совпадение. были найдены, что делает поиск потенциально менее затратным. Пути перечислены один раз для каждого искомого файла. Если стандарт ввод ищется, записывается строка "(стандартный ввод)".

Поскольку второй grepв вашем конвейере читает данные из стандартного ввода, а не из файла, он не знает, откуда берутся данные, кроме того, что они поступают в стандартный поток ввода. Вот почему он возвращает текстовую строку (стандартный ввод)(а не (стандартный вывод), как написано в вопросе). Это настолько близко, насколько это возможно, чтобы добраться до места, где находилась спичка.

Чтобы объединить два шаблона в первом grep(который действительнознает о том, в каких файлах он просматривается), см. «Как запустить grep с несколькими шаблонами AND». ?"

16
27.01.2020, 20:20

Вы можете поместить оба патерна в один запрос (на основе этого ответа), используя следующий шаблон:

grep -P '^(?=.*pattern1)(?=.*pattern2)'

В вашем случае вы можете добавить параметры -ir -l в следующем виде:

grep -irlP '^(?=.*pattern1)(?=.*pattern2)' .
2
27.01.2020, 20:20

(я предполагаю, что вы хотели, чтобы второй grep совпадал с содержимым строки, а не с имена файлов или оба, как ваш подход)

POSIXly:

find . -type f -exec awk '
  FNR == 1 {found = 0}
  !found && tolower($0) ~ /some string/ && /other string/ {
    print FILENAME
    found = 1
    nextfile
  }' {} +

Дело о найдено для реализаций awk, которые еще не поддерживают nextfile (и где nextfile не работает).Если вы знаете, что ваша реализация awk поддерживает nextfile , вы можете упростить ее до:

 find . -type f -exec awk 'tolower($0) ~ /some string/ && /other string/ {
    print FILENAME; nextfile}' {} +

С помощью GNU grep , созданной с поддержкой PCRE, так как вы хотите, чтобы одно совпадение быть нечувствительным к регистру, а не другим:

grep -rlP '^(?=.*(?i:some string))(?=.*other string)' .

(? = ...) - это оператор упреждающего просмотра perl . (? I: шаблон) включает соответствие без учета регистра только для шаблона . Итак, здесь мы сопоставляем начало строки ( ^ ) при условии, что за ним следует любое количество символов (. * ), за которым следует некоторая строка ( без учета регистра), а также то, что за ним (начало строки) следует любое количество символов и другая строка (с учетом регистра).

Если ваш grep не поддерживает -P , вы можете использовать команду pcregrep (замените grep -rlP на pcregrep -rl ), или если шаблоны не перекрываются, вы можете сделать:

grep -rl -e '[sS][oO][mM][eE] [sS][tT][rR][iI][nN][gG].*other string' \
         -e 'other string.*[sS][oO][mM][eE] [sS][tT][rR][iI][nN][gG]' .

Или, если вам все равно, оба совпадения нечувствительны к регистру:

grep -ril -e 'some string.*other string' \
          -e 'other string.*some string' .
5
27.01.2020, 20:20

Это самое короткое решение из всех предложенных.

find . -type f -exec perl -lne '
   /Some string/i and /other string/ and print($ARGV),close(*ARGV);
' {} +

grep -irZ "Some string" . |
perl -lsF'/\n/' -0ne '
   s/^/\n/ if $. == 1; s/$/\n/ if eof;

   $. == 1 and $prev = $F[1],next;
   push @{$h{$prev}}, $F[0];
   $prev = $F[1];

   END {
      grep($_ =~ /\Q${str2}/, @{$h{$_}}) and print for keys %h;
   }
' -- -str2="Another string"

Принцип работы: Здесь первый grep выполняет рекурсивный, нечувствительный к регистру поиск «какой-то строки» в текущем каталоге и вниз и генерирует нулевой разделитель( \0) записей из-за опции -Z, заданной для grep.

Каждая из этих записей содержит имя файла и совпавшую строку. Единственная загвоздка в том, что порядок не соответствует шагу из-за того, что grep не ставит \0 после соответствующей строки. Чтобы обойти это ограничение, мы используем Perl, читающий записи, разделенные нулями, и разделяющий эти записи на \n, чтобы отделить строки от имен файлов.

Следовательно, нет никаких ограничений на типы имен файлов, которые могут быть задействованы, за исключением \0, которые в любом случае запрещены.

1
27.01.2020, 20:20

Теги

Похожие вопросы