Как передать строки с одинарными кавычками в grep?

Как передать строки с одинарными кавычками в grep?

Мой желаемый результат следующий: рекурсивно искать в каталоге заданную строку во всех найденных файлах. Следующая команда — мой обычный порт вызова:

find ./ | xargs grep -ns 'foobar'

Однако, когда foobarесть кавычки, команда не выполняется и выдает мне >приглашение в оболочке. Конкретная команда, вызывающая проблему, следующая:

find ./ | xargs grep -ns 'add_action(\'save_post\','

Я пытался экранировать кавычки обратными косыми чертами, но безуспешно. Как правильно это сделать?

решение1

Одинарные кавычки завершаются одинарными кавычками; все остальные символы между ними сохраняются точно такими же, как есть, включая обратные косые черты. Таким образом, нет способа вставить одинарную кавычку между одинарными кавычками. (Но выможетзавершите одинарные кавычки, экранируйте одинарную кавычку и начните новый набор одинарных кавычек, как в 'Single quotes aren'\''t ever really embedded in single quotes.')

Предположение:Избегайте find+xargs, когда grep -r pattern .можно рекурсивно выполнить grep в текущем каталоге.

Приведенные ниже команды имеют эквивалентное поведение:

grep -rns "add_action('save_post'," .
grep -rns 'add_action('\'save_post\', .

Последняя команда интерпретируется как:

  1. 'add_action('->add_action(
  2. \'->'
  3. save_post->save_post
  4. \'->'
  5. ,->,

Объединяя эти части, grepкоманда получает аргумент add_action('save_post',.

решение2

xargsожидает аргументы, закавыченные каким-то странным образом, что findне производит. Никогда не используйте xargsв сочетании с find, если только вы не уверены, что имена ваших файлов не содержат \"'пробелов.

Вместо использования xargsдавайте findнапрямую вызовем программу, которую вы хотите запустить.

find . -exec grep -ns 'add_action('\''save_post'\'',' {} +

С помощью exec … {} +программа вызывается один раз для многих файлов одновременно, как и с xargs. Некоторые старые версии findне поддерживают +here¹, тогда вместо этого вам придется использовать ;, который вызывается grepодин раз для каждого файла.

В качестве альтернативы вы можете использовать find … -print0 | xargs -0, если ваши утилиты поддерживают это¹. Опция -print0указывает findвыдавать имена, разделенные нулевым байтом, и -0указывает xargsожидать ввода, разделенного нулем, и не выполнять никакой интерпретации кавычек.

Обратите внимание на кавычки выше: между одинарными кавычками все символы интерпретируются буквально, за исключением того, что 'обозначает конец буквальной строки. Так что '\''это фактически способ поместить буквальную одинарную кавычку внутрь строки в одинарных кавычках; формально это « 'конечная кавычка, \буквальная 'одинарная кавычка, 'начальная кавычка».

В особом случае grep, если ваша реализация поддерживает это¹, вы можете обойтись без него findи использовать grep -rдля рекурсивного поиска внутри каталога:

grep -r 'add_action('\''save_post'\'',' .

¹ Linux, Cygwin, FreeBSD и OSX поддерживают эти функции.

решение3

grep "add_action('save_post'," ./* -R
  1. Вы можете рекурсивно выполнить grep всех файлов в текущем каталоге с помощью -Rопции.

  2. Строку поиска можно заключить в ".

Связанный контент