различные способы поиска двух разных строк, появляющихся в любом порядке, или строки в одном файле - PullRequest
0 голосов
/ 24 мая 2018

Я хочу вернуть все файлы со строками: "main(", а также "foo".

Это похоже на использование многопользовательского OR grep, но вместо AND.

Лучшее, что я придумал, это:

grep -rl . -e "main("|while read fname; do grep -rl "$fname" -e "foo"; done

Это делает свою работу, но в идеале мне не пришлось бы писать скрипт bash.

Например

text1.txt:

int main()
{
    stuff....
}

foo

Команда grep вернет text1.txt, поскольку она содержит строки 'main (' и 'foo'

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Попробуйте

grep -rlZ 'main(' | xargs -0 grep -l 'foo'

-Z, --null Вывести нулевой байт (символ ASCII NUL) вместо символа, который обычно следует за именем файла.Например, grep -lZ выводит нулевой байт после каждого имени файла вместо обычной новой строки.Эта опция делает вывод однозначным, даже при наличии имен файлов, содержащих необычные символы, такие как переводы строк.Эта опция может использоваться с такими командами, как find -print0, perl -0, sort -z и xargs -0 для обработки произвольных имен файлов, даже тех, которые содержат символы новой строки.


Первый grep напечатает все имена файлов, содержащие main(, разделенные символом NUL.xargs будет передавать файлы второй команде grep, которая будет печатать файлы, содержащие foo


Если файлы достаточно малы и не содержат символ NUL,

grep -rlz 'main(.*foo\|foo.*main('

, где -z будет использовать NUL в качестве разделителя строк, эффективно удаляя весь файл

0 голосов
/ 24 мая 2018

Просто используйте awk для сопоставления шаблонов и имен файлов печати:

awk 'FNR == 1 { m = f = 0 }         # reset flags at start of each file
     /main\(/ { ++m } /foo/ { ++f } # set flags when patterns match
     m && f { print FILENAME; nextfile }' **/*

nextfile - это расширение GNU, которое пропускает к следующему файлу, а не к следующей строке.При включенном globstar ** рекурсивно расширяется.В интерактивной оболочке bash она включена по умолчанию, но в сценарии вы можете включить ее самостоятельно, используя shopt -s globstar.

. При использовании не-GNU awk вы можете использовать другой флаг, чтобы пропустить строки и избежать печатиимя файла несколько раз:

awk 'FNR == 1 { m = f = p = 0 } # reset flags at start of each file
     p { next }                 # skip lines once this filename has been printed
     /main\(/ { ++m } /foo/ { ++f } 
     m && f { print FILENAME; ++p }' **/*
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...