Почему grep не возвращает то, что я ожидаю, когда я использую одинарные кавычки?

Почему grep не возвращает то, что я ожидаю, когда я использую одинарные кавычки?

У меня есть файл со следующим содержимым:

sh-4.2$ cat file1
example of multiple
pattern
this is an
example of multipole
sorry multiple
pattern matching
using grep
so the example is the
file itself
-example
-multiple
-bye
tata
!

При поиске "-example" в указанном выше файле команда grep не выдает желаемый вывод. Я знаю, что если шаблон содержит '-', то следует использовать опцию -e:

В первом примере я использовал-примернапрямую, без кавычек:

sh-4.2$ grep -example file1
example of multiple
example of multipole
so the example is the
-example

-примерс одинарными кавычками:

sh-4.2$ grep '-example' file1
example of multiple
example of multipole
so the example is the
-example

-примерс двойными кавычками и экранированными символами

sh-4.2$ grep "\-example" file1
-example
sh-4.2$

решение1

Ну, вы знаете, что шаблон поиска содержит '-', и вы знаете, что когда шаблон поиска содержит '-', вам нужно использовать флаг -e. Поскольку вы не используете флаг, -eоболочка интерпретирует ваш "шаблон" как аргумент (и параметр) вместо этого. Вы можете увидеть это с помощью:

$ grep "-foo" file1
grep: oo: No such file or directory

По сути, ваш код grep "-example" file1сообщает оболочке, что вы хотите запустить ее grepс -eаргументом и параметром «xample».

Это та же проблема, с которой мы сталкиваемся, когда пытаемся что-то вроде rm -my-silly-file-name— это не сработает, и нам нужно использовать что-то вроде rm ./-my-silly-file-name. Другим обходным решением будет rm -- -my-silly-file-name. Мы можем использовать эту идиому здесь:

$ grep -- "-example" < file1
-example

Символ «--» сообщает оболочке, что все, что находится после него,нетАргумент.

В качестве альтернативы вы можете просто экранировать «-» с помощью «\», как вы видели:

grep "\-example" file1

В этой статье подробно рассматриваются некоторые детали цитирования.: соответствующая частьПараметры и команды в обратных кавычках, которые должны интерпретироваться оболочкой, заключаются в двойные кавычки.При использовании двойных кавычек содержимое интерпретируется оболочкой.

решение2

Вы «знаете, что если шаблон [начинается с] '-', то следует использовать опцию -e», но не используете ее, когда следует. grep -e -example file1даст вам ожидаемый результат.

Вот что на самом деле выполняется в каждом из ваших примеров:

  • grep -example file1=> grep -e xample file1(-e необходимо)
  • grep '-example' file1=> grep -e xample file1(-e необходимо)
  • grep "\-example" file1=> grep \-example file1(-e не обязательно)

решение3

Аргумент, начинающийся с , -принимается как вариант.

В первых двух случаях первым переданным аргументом grepявляется -example, который grepпонимается как -e xample( xampleаргумент опции -e, поэтому ищите xample).

В третьем случае \-exampleпередается в grep. Так как он не начинается с -, он не воспринимается как опция. Вместо этого он воспринимается как регулярное выражение. Однако поведение для \-не определено в соответствии с POSIX, поэтому у вас нет гарантии относительно того, что именно ему соответствует. В большинстве grepреализаций \-будет соответствовать -, однако вы можете представить grepреализации, где \-может быть специальным оператором (см., например, GNU, grepгде \+является специальным оператором и не соответствует литералу +).

Если вы -exampleне хотите, чтобы вас рассматривали как вариант, вам необходимо:

  • grep -- -example file. Знак --обозначает конец опций. Все, что после него, не является опцией (поэтому первый аргумент — это шаблон для поиска, а остальные — список файлов для поиска).
  • grep -e -example file. Здесь -exampleпринимается как аргумент к -eварианту.

Вот почему вам стоит привыкнуть писать:

grep -e "$pattern" file

Или

grep -- "$pattern" file

если вы не можете гарантировать, $patternчто не начнется с -.

Обратите внимание, что здесь вы также можете написать:

grep '[-]example' file

Хотя см.Выражение в квадратных скобках (без диапазонов), соответствующее неожиданному символу в bashо возможных осложнениях при таком подходе.

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