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

146

Когда я ищу вкладки в файле с помощью (e) grep, я использую буквенную вкладку ( ^v + <tab>). Я не могу использовать \tв качестве замены для вкладок в регулярных выражениях. Например, у sed это выражение работает очень хорошо.

Так есть ли возможность использовать нелитеральную замену <tab>и каковы предпосылки для неработающего / не интерпретированного \t?

Lasall
источник
stackoverflow.com/questions/1825552/grep-a-tab-in-unix
Чиро Сантилли 新疆 改造 中心 法轮功 六四 事件

Ответы:

206

grep использует регулярные выражения, определенные в POSIX . По тем или иным причинам POSIX не определен \tкак таб.

У вас есть несколько вариантов:

  • скажите grep использовать регулярные выражения, как определено в perl (perl имеет \tas tab):

    grep -P "\t" foo.txt

    Страница man предупреждает, что это «экспериментальная» функция. по крайней мере, \tкажется, работает нормально. но более продвинутые возможности Perl Regex могут и не быть.

  • используйте printf, чтобы напечатать символ табуляции для вас:

    grep "$(printf '\t')" foo.txt
  • используйте буквенный символ табуляции:

    grep "^V<tab>" foo.txt

    то есть: введите grep ", затем нажмите ctrl+v, затем нажмите tab, затем введите " foo.txt. нажатие ctrl+vв терминале приводит к тому, что следующая клавиша принимается дословно. это означает, что терминал будет вставлять символ табуляции вместо вызова какой-либо функции, связанной с клавишей табуляции.

  • используйте особую цитату в bash:

    grep $'\t' foo.txt

    это работает не во всех оболочках.

  • используйте awk:

    awk '/\t/'
  • используйте sed:

    sed -n '/\t/p'

См. Статью в Википедии о регулярных выражениях для обзора определенных классов символов в POSIX и других системах.

lesmana
источник
основываясь на ответе энзотиба, позвольте мне добавить следующее: grep $'\t' foo.txt(но я бы обычно писал fgrepвместо grep)
Уолтер Тросс
Мне это нужно, в сочетании с использованием значения переменной среды. Я использовал grep "$(printf '\t')${myvar}" foo.txt. Работало нормально. После нескольких попыток я не смог заставить работать последнюю форму.
sancho.s
1
Есть ли какая-то причина, по которой равнина grepне может молча интерпретировать \tкак табуляцию? POSIX требует, чтобы это \tозначало что-то еще? Возможно, он должен соответствовать только литералу с \ последующим t?
Аарон МакДейд
Возможно, стоит отметить, что в BSD (включая OSX) grep отсутствует опция -P.
TextGeek
Со страницы руководства This is highly experimental and grep -P may warn of unimplemented features.Вероятно, не очень хорошая идея использовать -Pв устаревших системах. printfВыбор лучше
Avindra Goolcharan
13

Это не совсем тот ответ, который вы хотели бы услышать, но возможное использование escape-последовательностей обеспечивается bash

command | grep $'\t'

(не помещайте это в двойные кавычки!).

enzotib
источник
1
нет необходимости в -E (то, что ищется, не является регулярным выражением). Также нет необходимости передавать данные из команды. Тем не менее, спасибо, что указали на эту довольно упущенную особенность bash (строки в одинарных кавычках, перед которыми
стоит
2
Действительно, я предлагаю @enzotib отредактировать ответ так, чтобы он был простым grep $'\t'.
Теему Лейсти
Следует подчеркнуть, что это особенность bash, и она (молча!) Будет делать неправильные вещи, если выполняется другой оболочкой (например, dash, которая используется по умолчанию для сценариев оболочки в Ubuntu и других)
xjcl
2

awk '/\t/' мой любимый обходной путь:

printf 'a\t\nb' | awk '/\t/'

Выход: a\t.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
источник
1

Всегда можно прибегнуть к использованию шестнадцатеричного кода ascii для табуляции:

$ echo "one"$'\t'"two" > input.txt                                 

$ grep -P "\x9" input.txt                                          
one two

$ grep $'\x9' input.txt                                            
one two
Сергей Колодяжный
источник