1

Я не уверен, что я не полностью понимаю grep или регулярные выражения являются источником моей проблемы, поэтому у меня есть два вопроса. У меня есть простой тестовый файл с именем test.txt со следующим содержимым:

$ cat test.txt Settings.xml blah Settings_1.xml blah Settings_2.xml

Когда я запускаю grep в каталоге, содержащем только указанный выше тестовый файл, с помощью следующей команды, он возвращается без совпадений:

$ grep -ir "Settings*xml"

1) Почему подстановочный знак * не перехватывает точку?

И когда я запускаю grep как таковой:

$ grep -ir "Settings*.xml"

единственная разница заключается в том, что период после подстановочного знака приводит к следующим результатам:

test.txt:Settings.xml

2) Почему grep не находит другие два совпадения?

2 ответа2

3

Причина в том, что * является специальным символом в регулярных выражениях и означает zero or more preceding characters . Вы должны экранировать * чтобы обозначить буквальный * символ с \ . Итак, в ваших примерах:

grep -ir "Settings*xml"

будет искать строку, которая начинается с Setting , а затем имеет ноль или более символов s и xml в конце. В вашем файле нет такой строки, потому что xml всегда предшествует . , И это:

grep -ir "Settings*.xml"

будет искать строку, которая начинается с Setting , а затем имеет ноль или более s и .xml после ноля или более s букв.

Ваш первый регулярное выражение будет соответствовать что-то вроде этого:

Settingssxml

1

Этот другой ответ объясняет, что произошло, он отвечает на ваши четкие вопросы. Мой ответ призван представить более широкий контекст.

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

$ ls -1
Settings.xml
blah
Settings_1.xml
Settings_2.xml

тогда (скажем, в bash) вы можете сделать:

$ echo Settings*.xml
Settings.xml Settings_1.xml Settings_2.xml

Вы не получили того, что ожидали, потому что grep использует синтаксис регулярных выражений, где:

  • . соответствует (почти) любому персонажу,
  • * означает "ноль или более предшествующих символов",
  • \ заставляет следующий символ интерпретироваться буквально.

Поэтому вместо "Settings*.xml" вы должны были использовать "Settings.*\.xml". В этом случае:

  • .* делает то, что думал * сделает,
  • \. делает то, что ты думал . сделал бы.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .