Регулярное выражение с использованием \\ vs с использованием \

Почему

grep e\\.g\\. <<< "this is an eg wow" 

а также

 grep e\.g\. <<< "this is an eg wow" 

делать то же самое?

Если я добавлю третий косой черты, он также будет иметь тот же результат. НО, как только я добавлю четвертую черту, она больше не работает. Это связано с вопросом со старого экзамена на класс. Он спросил, будет ли один с двумя обратными косыми чертами работать для вывода строки с «например», я изначально думал, что это не сработает, но я попытался убедиться, и это произошло. Какое объяснение?

  • синтаксис grep для поиска строк с одиночными кавычками?
  • Как поймать сигнал в командной строке?
  • Программирование оболочки, исключая временные файлы
  • Почему `grep fil *` терпит неудачу?
  • Написание сценария оболочки для вывода исполняемого файла и выполнения некоторых вычислений
  • Помощь с использованием кавычек в поиске grep
  • Как выполнить несколько команд вместе в фоновом режиме?
  • Игнорировать все совпадения для отрицательного шаблона extglob в рекурсивном ls
  • 4 Solutions collect form web for “Регулярное выражение с использованием \\ vs с использованием \”

    Во-первых, обратите внимание, что однократное совпадение слишком сильно:

     $ echo $'eegg \n eg' | grep e\.g\. eegg eg 

    Что касается Bash , то период сбежания совпадает с периодом. Баш переходит на период до grep . Для grep период соответствует чему-либо.

    Теперь рассмотрим:

     $ echo $'eegg \n eg' | grep e\\.g\\. eg $ echo $'eegg \n eg' | grep e\\\.g\\\. eg $ echo $'eegg \n eg' | grep e\\\\.g\\\\. $ 

    Когда Bash видит двойную косую черту, она сводится к одной косой черте и передает ее на grep, который в первом из трех тестов выше видит, как мы хотим, одну косую черту перед периодом. Таким образом, это правильно.

    С тройной косой чертой Bash сокращает первые два до одной косой черты. Затем он видит \. , Поскольку беглый период не имеет особого значения для Bash, это сводится к простому периоду. В результате grep видит, как мы хотим, косую черту перед периодом.

    С четырьмя чертами Bash уменьшает каждую пару до одной косой черты. Бэш переходит к grep двум слэшам и периоду. grep видит две слэши и период и уменьшает две слэши до единственной литеральной косой черты. Если на входе нет буквальной косой черты, за которой следует любой символ, совпадений нет.

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

     $ echo 'eegg eg e\.g\.' | grep e\\\\.g\\\\. e\.g\. 

    Резюме поведения Баша

    Для Баша правила

    • Две черты сокращены до одной косой черты.

    • Слэш перед нормальным символом, как период, является обычным символом (периодом).

    Таким образом:

     $ echo \. \\. \\\. \\\\. . \. \. \\. 

    Существует простой способ избежать этой путаницы: в командной строке Bash регулярные выражения должны быть помещены в одиночные кавычки. Внутри одиночных кавычек Баш оставляет все в покое.

     $ echo '\. \\. \\\. \\\\.' # Note single-quotes \. \\. \\\. \\\\. 

    Результат такой же для вашей строки, но в целом эти регулярные выражения делают разные вещи. Немного изменим ваш пример, добавив второй образец e,g, (с комами), третий e\.g\. (точки), четвертый e\,g\, (comas) и -o вариант grep для печати только совпадающих частей.

    • В следующем случае . сопоставить любой символ (уведомление '' вокруг, eg , я приду позже»)

       $ grep -o 'eg' <<< grep -o 'eg' <<< 'this is an eg e,g, e\.g\. e\,g\,' eg e,g, 
    • Затем мы убежим . с обратной косой чертой \ , так что только буквально . будет соответствовать:

       $ grep -o 'e\.g\.' <<< 'this is an eg e,g, e\.g\. e\,g\,' eg 
    • Но мы можем убежать \ с другим \ , так что буквальный \ будет соответствовать следующему . (т. е. любой символ):

       $ grep -o 'e\\.g\\.' <<< 'this is an eg e,g, e\.g\. e\,g\,' e\.g\. e\,g\, 
    • Но если мы хотим соответствовать только \. не \, то еще один \ необходим, чтобы избежать особого значения точки:

       $ grep -o 'e\\\.g\\\.' <<< 'this is an eg e,g, e\.g\. e\,g\,' e\.g\. 

    Теперь, поскольку вы не использовали аргумент grep, вы должны добавить еще одну обратную косую черту, чтобы избежать обратной косой черты из интерпретации оболочки, поэтому:

     grep 'e\.g\.' => grep e\\.g\\. grep 'e\\.g\\.' => grep e\\\\.g\\\\. (each backslash has to be quoted separately) grep 'e\\\.g\\\.' => grep e\\\\\\.g\\\\\\. (3 x 2 = 6 backslashes in total) 

    Когда вы делаете grep e\.g\. , оболочка потребляет обратную косую черту, таким образом, вы выполняете grep eg , который соответствует. Когда вы делаете grep e\\.g\\. , оболочка снова потребляет косую черту, и теперь вы делаете grep e\.\g. , который снова совпадает. Теперь обратная косая черта в оболочке выглядит как \\ . Итак, когда у вас \\ , первая – это escape-последовательность, вторая – буквальная обратная косая черта. Когда вы делаете grep e\\\.g\\\. , он все равно заканчивается grep e\.\g. , потому что перед первой \ не существует escape-последовательности ( \ ), чтобы сделать ее литералом \ . Имейте в виду, что \ это обратная косая черта, поэтому grep e\\\\.\\\\g заканчивается grep e\\.g\\. , что явно не соответствует.

    Чтобы увидеть, как оболочка видит, что вы делаете, используйте эхо (например, echo grep e\\.g\\. <<< "this is an eg wow" vs. echo grep e\\\\.g\\\\. <<< "this is an eg wow" ).

    Эти две команды производят один и тот же вывод только для вашего ввода, но в остальном они разные. Для понимания того, что происходит, мы должны знать, как параметр интерпретируется сначала bash а затем grep .

    Побег в bash

    \ – специальный символ, который отменяет особый смысл следующего символа, включая \ себя. Если следующий символ не имеет особого значения, он передается без изменений. Примеры с командой и результат:

    • echo \a : a – обычный символ, сбежавший, дает символ
    • echo \\ : \ – специальный символ escaped дает символ
    • echo \\\a : \a – комбинация специальная, обычная
    • echo \\\\ : \\ – комбинация специальная, специальная

    echo будет печатать полученную строку после того, как bash интерпретирует ее. Дополнительная информация: документация bash, wiki-хакеры хакеров , спецификация POSIX .

    . не имеет особого значения в bash . Это обычный символ для оболочки. Ниже приведены последовательности, относящиеся к вашим примерам:

    • echo . : .
    • echo \. : .
    • echo \\. : \.
    • echo \\\. : \.
    • echo \\\\. : \\.

    Упрощенное решение для литеральных строк в bash

    Чтобы передавать параметры буквально с помощью bash вы можете использовать одиночную кавычку ' экранирование». Между одинарными кавычками вам не нужно заботиться о специальном значении символов, потому что одиночная кавычка является единственным персонажем со специальным значением. Вы можете вставить одну цитату после включения первой части строки. Пример:
    echo 'part1'\''part2' : part1'part2

    Регулярное выражение в grep

    \ является escape-символом с аналогичным значением, как в bash . . является особым символом, который представляет собой одиночное появление любого символа . См. POSIX regex , GNU grep regex . Примеры выражений регулярных выражений:

    • . – соответствует любому символу, например a или .
    • \. – соответствует только . буквально

    Ваши примеры

    Во второй строке каждого примера ниже вы найдете эквивалент с одинарными кавычками ' показывающими, какая строка букв передается bash в grep . Затем, после того, как grep выполнит выход, в примерах будет только единственный специальный символ . сопоставляя любой символ. На третьей строке есть описание того, что соответствует выражению.

    • grep eg <<< "this is an eg wow"
      grep 'eg' <<< "this is an eg wow"
      e любой символ g любой символсоответствует, eg и, возможно, другим строкам, таким как eagb
    • grep e\.g\. <<< "this is an eg wow"
      grep 'eg' <<< "this is an eg wow"
      e любой символ g любой символсоответствует, eg и, возможно, другим строкам, таким как exgy
    • grep e\\.g\\. <<< "this is an eg wow"
      grep 'e\.g\.' <<< "this is an eg wow"
      eg буквально – соответствует, eg только
    • grep e\\\.g\\\. <<< "this is an eg wow"
      grep 'e\.g\.' <<< "this is an eg wow"
      eg буквально – соответствует, eg только
    • grep e\\\\.g\\\\. <<< "this is an eg wow"
      grep 'e\\.g\\.' <<< "this is an eg wow"
      e\ любой символ g\ любой символне соответствует, eg
    Linux и Unix - лучшая ОС в мире.