Я ищу способ поиска файлов, где два экземпляра слова существуют в одном файле. До этого момента я использовал следующее для поиска:
find . -exec grep -l "FIND ME" {} \;
Проблема, с которой я сталкиваюсь, заключается в том, что если между "НАЙТИ" и "МЕНЯ" нет точно одного пробела, результат поиска не даст файл. Как мне адаптировать старую строку поиска, где в файле существуют оба слова «НАЙТИ» и «Я», а не «НАЙТИ МЕНЯ»?
Я использую AIX.
grep -E
/,egrep
которое описывает все шаблоны, которые вас интересуют (и использование+
вместо,;
если ваша находка имеет поддержку+
.Ответы:
С инструментами GNU:
Вы можете сделать стандартно:
Но это будет запускать два greps на файл. Чтобы избежать запуска такого количества
grep
s и при этом быть переносимым, при этом допуская любой символ в именах файлов, вы можете сделать:Идея состоит в том, чтобы преобразовать вывод
find
в формат, подходящий для xargs (который ожидает пробел (SPC / TAB / NL и другие пробелы в вашей локали с некоторыми реализациямиxargs
), разделенного списка слов, где одинарные, двойные кавычки и обратные слеши могут избегать пробелов и друг друга).Как правило, вы не можете постобработать вывод
find -print
, потому что он разделяет имена файлов символом новой строки и не экранирует символы новой строки, которые встречаются в именах файлов. Например, если мы видим:У нас нет никакой возможности узнать, называется ли это один файл
b
в каталогеa<NL>.
или это два файлаa
иb
.Используя
.//.
, потому что//
иначе не может появиться в пути к файлу как выводfind
(потому что не существует такой вещи, как каталог с пустым именем и/
не допускается в имени файла), мы знаем, что если мы увидим строку, которая содержит//
, то это первая строка нового имени файла. Таким образом, мы можем использовать этуawk
команду для экранирования всех символов новой строки, кроме тех, которые предшествуют этим строкам.Если мы возьмем приведенный выше пример,
find
будет выводиться в первом случае (один файл):Какой awk уходит в:
Так что
xargs
это воспринимается как один аргумент. И во втором случае (два файла):Который
awk
оставил бы как есть, такxargs
видит два аргумента.источник
find ... -print0
иgrep --null
вместо этого?grep --null
(aka -Z) используется в первом, но является расширением GNU.-print0
(другое расширение GNU) здесь не поможет..//.
еще значит, и интересно, как я могу изменить это, чтобы принять аргумент из командной строки, скажем$1
?-print0
сfind
и-0
сxargs
?find -print0
нигде не использую в своем ответе.Если файлы находятся в одном каталоге и их названия не содержат пробел, табуляция, перевод строки,
*
,?
ни[
символов и не начать с-
ни.
, это будет получить список файлов , содержащих ME, то сузить , что вплоть до тех , которые также содержат НАЙТИ.источник
grep -l CategoryLinearAxis `grep -l labelJsFunction *`
при поиске файлов с обоими атрибутами. Какой идеальный способ сделать это. +1С
awk
вами также можно запустить:Он использует
cx
иcy
для подсчета совпадений строкFIND
и соответственноME
. ВEND
блоке, если оба счетчика> 0, он печатаетFILENAME
.Это было бы быстрее / эффективнее с
gnu awk
:источник
Или используйте
egrep -e
илиgrep -E
как это:find . -type f -exec egrep -le '(ME.*FIND|FIND.*ME)' {} \;
или
find . -type f -exec grep -lE '(ME.*FIND|FIND.*ME)' {} +
Команда
+
make find (если поддерживается) добавляет несколько имен файлов (путей) в качестве аргументов для редактируемой команды-exec
. Это экономит процессы и выполняется намного быстрее, чем\;
команда, которая вызывает команду один раз для каждого найденного файла.-type f
соответствует только файлам, чтобы избежать поиска в каталоге.'(ME.*FIND|FIND.*ME)'
является регулярным выражением, совпадающим с любой строкой, содержащей «ME», за которой следует «FIND» или «FIND», а затем «ME». (одинарные кавычки, чтобы оболочка не интерпретировала специальные символы).Добавьте
-i
кgrep
команде, чтобы сделать ее без учета регистра.Используйте только строки, где «НАЙТИ» предшествует «Я», используйте
'FIND.*ME'
.Требовать пробелы (1 или более, но не более) между словами:
'FIND +ME'
Чтобы разрешить пробелы (0 или больше, но ничего больше) между словами:
'FIND *ME'
Комбинации бесконечны с регулярными выражениями, и при условии, что вы заинтересованы в сопоставлении только по строкам за раз, egrep очень эффективен.
источник
find
в вопросе.Глядя на принятый ответ, он кажется более сложным, чем нужно. Версии GNU
find
иgrep
иxargs
поддерживают строки, заканчивающиеся на NULL. Это так просто, как:Вы можете изменить свою
find
команду для фильтрации файлов, которые вы хотите, и она работает с именами файлов, содержащими любой символ; без дополнительной сложностиsed
разбора. Если вы хотите продолжить обработку файлов, добавьте еще один--null
к последнемуgrep
И, как функция:
Очевидно, используйте принятый ответ, если вы не используете GNU-версии этих инструментов.
источник
--null
,--print0
,-0
Все расширения GNU. Хотя некоторые из них сейчас встречаются в других реализациях, они все еще не переносимы и не соответствуют стандарту POSIX или Unix.