Почему в моем выражении grep нужно использовать $ 'string' для соответствия символам табуляции?

Если вы возьмете этот код:

echo -e '\t\t\tString' | grep '^[\t]*String' 

результат пуст, потому что он не совпадает, но это:

 echo -e '\t\t\tString' | grep $'^[\t]*String' 

работает. Я клянусь, что я, должно быть, использовал код первой строки сто раз в своих сценариях и в терминале, но никогда не использовал символ «$», и это всегда казалось сработавшим. Произошли ли какие-то недавние изменения? Зачем нужен символ «$»? Или я делаю что-то неправильно?

3 Solutions collect form web for “Почему в моем выражении grep нужно использовать $ 'string' для соответствия символам табуляции?”

Котировка ANSI-C

Согласно руководству Bash, это называется цитированием ANSI-C . В руководстве написано:

Слова формы $ 'string' обрабатываются специально. Слово расширяется до строки с заменой символов с обратным слэшем, как указано в стандарте ANSI C.

На практике это означает, что '\t' не будет расширен в символ табуляции, а $'\t' будет. Результат должен быть эквивалентен использованию echo -e , но может использоваться везде, где вы использовали бы строку без необходимости замены команд .

Утилиты, такие как GNU sed, выполняют собственное расширение escape-символов, но GNU grep этого не делает. Оболочка Bash, а не grep, расширяет экранированные символы в цитированных строках ANSI-C. Без цитирования ANSI-C регулярное выражение, которое вы указали, не содержит символов табуляции в соответствии с вводом.

Вероятно, вам следует понять, что нет единого типа регулярных выражений. Существуют, по крайней мере, basic regular expressions или BRE (иногда только RE ), extended regular expressions или ERE и perl compatible regular expressions или PCRE . Все эти языки используют несколько иной синтаксис. Текущие версии GNU grep поддерживают все три, а BRE – по умолчанию. Для ERE вам необходимо использовать опцию -E и для опции PCRE -P . Ваш пример будет работать только с -P поскольку с базовым и расширенным RE обратная косая черта теряет смысл, а [\t] соответствует либо косой чертой, либо символом t. Вероятно, вы использовали этот шаблон на каком-то другом языке, который по умолчанию поддерживает PCRE , что имеет смысл, поскольку они являются самой мощной версией. Или, возможно, у вас был alias grep='grep -P' .

Первая строка работает, если вы не укажете ^ . Возможно, это сработало, но это не сработало так, как вы предполагали? Я сомневаюсь, что поведение grep изменилось в такой важной точке.

echo не переводит escape-последовательности по умолчанию. Для этого вам нужен -e . Аналогично оболочке. Вам нужно $'...' чтобы заставить оболочки использовать escape-последовательности.

  • Сценарий Bash не конвертирует переменные
  • while: команда не найдена
  • Какие символы мне нужно избегать при использовании sed в сценарии sh?
  • Скобка в команде echo shell
  • Почему мы дважды цитируем оценку знака доллара в Bash?
  • Есть ли причина, чтобы указать статус выхода $? переменная?
  • Проблема использования пользовательской переменной в скрипте
  • Передача аргументов с кавычками и двойными значениями в сценарий bash
  • Не удалось получить команду для работы с bash -c
  • Почему -text = "$ @" пропускает только первое слово?
  • Одинарная кавычка в двойных кавычках и справочное руководство Bash
  • Linux и Unix - лучшая ОС в мире.