Как мне grep
вставить (\ t) в файлы на платформе Unix?
Как мне grep
вставить (\ t) в файлы на платформе Unix?
Ответы:
Если вы используете GNU grep, вы можете использовать регулярное выражение в стиле Perl:
grep -P '\t' *
-P
варианте.
Хитрость заключается в использовании знака $ перед одинарными кавычками. Это также работает для резки и других инструментов.
grep $'\t' sample.txt
zsh
а также, насколько я могу судить. Не могли бы вы прокомментировать семантику этого $
знака?
$'\t'' '
. Реальный пример, который показывает, что он работает также с sh (не только bash, который по умолчанию не установлен на Android) - это busybox grep -oE '^nodev'$'\t''fuse$' /proc/filesystems
.
Мне никогда не удавалось заставить метасимвол '\ t' работать с grep. Однако я нашел два альтернативных решения:
<Ctrl-V> <TAB>
(нажатие Ctrl-V, затем ввод с клавиатуры)foo | awk '/\t/'
| awk '/\t/'
Решение будет работать для всех оболочек, платформ и систем.
awk
Здесь хорошо работает, но в некоторых тестах на моей машине с очень большими файлами это примерно на 30% медленнее, чем при использовании grep -P
. Это может быть тривиально и неактуально в зависимости от варианта использования, а awk
может быть лучше просто для удобства чтения и переносимости.
Из этого ответа на Ask Ubuntu:
Скажите grep использовать регулярные выражения, как определено в Perl (Perl имеет
\t
вкладку):grep -P "\t" <file name>
Используйте буквенный символ табуляции:
grep "^V<tab>" <filename>
Используйте
printf
для печати символа табуляции для вас:grep "$(printf '\t')" <filename>
Один способ (это с Bash)
grep -P '\t'
-P
включает регулярные выражения Perl, так что \ t будет работать.
Как говорит пользователь unwind , это может быть связано с GNU grep. Альтернативой является буквально вставить туда вкладку, если оболочка, редактор или терминал это разрешат.
Еще один способ вставить вкладку буквально в выражение - использовать менее известную $'\t'
цитату в Bash:
grep $'foo\tbar' # matches eg. 'foo<tab>bar'
(Обратите внимание, что если вы подходите для фиксированных строк, вы можете использовать это в режиме '-F'.)
Иногда использование переменных может сделать запись более читабельной и управляемой:
tab=$'\t' # `tab=$(printf '\t')` in POSIX
id='[[:digit:]]\+'
name='[[:alpha:]_][[:alnum:]_-]*'
grep "$name$tab$id" # matches eg. `bob2<tab>323`
Это не совсем то, что вы ищете, но может работать в вашем случае
grep '[[:blank:]]'
Эквивалентно
grep -P '[ \t]'
Так он найдет пробел и таб.
Обратите внимание, это не рекламируется по моему man grep
, но все еще работает
$ man grep | grep blank | Туалет 0 0 0
-P
аргумент добавлен.
Есть два основных способа решения этой проблемы:
( Рекомендуется ) Используйте синтаксис регулярного выражения, поддерживаемый grep (1). Современный grep (1) поддерживает две формы синтаксиса регулярных выражений POSIX 1003.2: базовые (устаревшие) RE и современные RE. Синтаксис подробно описан на man-страницах re_format (7) и regex (7), которые являются частью систем BSD и Linux соответственно. GNU grep (1) также поддерживает Perl-совместимые RE, предоставляемые библиотекой pcre (3).
На языке регулярных выражений символ табуляции обычно кодируется \t
атомом. Атом поддерживается BSD расширенного регулярных выражений ( egrep
, grep -E
на BSD совместимой системы), а также на Perl-совместимых УЭ ( pcregrep
ГНУ grep -P
).
Как базовые регулярные выражения, так и расширенные RE Linux, по-видимому, не поддерживают \t
. Обратитесь к справочной странице утилиты UNIX, чтобы узнать, какой язык регулярных выражений он поддерживает (отсюда разница между регулярными выражениями sed (1), awk (1) и pcregrep (1)).
Поэтому в Linux:
$ grep -P '\t' FILE ...
На BSD похожей системе:
$ egrep '\t' FILE ...
$ grep -E '\t' FILE ...
Передайте символ табуляции в шаблон. Это просто, когда вы редактируете файл скрипта:
# no tabs for Python please!
grep -q ' ' *.py && exit 1
Однако при работе в интерактивной оболочке вам может потребоваться использовать возможности оболочки и терминала для ввода правильного символа в строку. На большинстве терминалов это можно сделать с помощью комбинации клавиш Ctrl
+, V
которая инструктирует терминал обрабатывать буквально следующий вводимый символ ( V
дословно):
$ grep '<Ctrl>+<V><TAB>' FILE ...
Некоторые оболочки могут предлагать расширенную поддержку для набора команд. Такие, в bash (1) слова формы $'string'
обрабатываются специально:
bash$ grep $'\t' FILE ...
Пожалуйста, обратите внимание, хотя, будучи хорошим в командной строке, это может вызвать проблемы совместимости, когда скрипт будет перемещен на другую платформу. Кроме того, будьте осторожны с кавычками, когда используете специальные предложения, пожалуйста, обратитесь к bash (1) для деталей.
Для оболочки Bourne (и не только) такое же поведение можно эмулировать, используя подстановку команд, дополненную printf (1), для создания правильного регулярного выражения:
$ grep "`printf '\t'`" FILE ...
используйте gawk, установите разделитель полей на tab (\ t) и проверьте количество полей. Если больше 1, то есть / есть вкладки
awk -F"\t" 'NF>1' file
awk /\t/
достаточно для вопроса оп.
Хороший выбор - использовать sed as grep (как объясняется в этом классическом уроке sed ).
sed -n 's/pattern/&/p' file
Примеры (работает в bash, sh, ksh, csh, ..):
[~]$ cat testfile
12 3
1 4 abc
xa c
a c\2
1 23
[~]$ sed -n 's/\t/&/p' testfile
xa c
a c\2
[~]$ sed -n 's/\ta\t/&/p' testfile
a c\2
+1 способ, который работает в ksh, dash и т.д .: используйте printf для вставки TAB:
grep "$(printf 'BEGIN\tEND')" testfile.txt
grep "$(printf '\t')" testfile.txt
Использование метода «sed-as-grep», но замена вкладок видимым символом личных предпочтений - мой любимый метод, поскольку он четко показывает, какие файлы содержат запрашиваемую информацию, а также где она находится в строках:
sed -n 's/\t/\*\*\*\*/g' file_name
Если вы хотите использовать информацию о строке / файле или другие параметры grep, но также хотите увидеть видимую замену символа табуляции, вы можете добиться этого с помощью
grep -[options] -P '\t' file_name | sed 's/\t/\*\*\*\*/g'
Например:
$ echo "A\tB\nfoo\tbar" > test
$ grep -inH -P '\t' test | sed 's/\t/\*\*\*\*/g'
test:1:A****B
test:2:foo****bar
РЕДАКТИРОВАТЬ: Очевидно, что выше это полезно только для просмотра содержимого файла, чтобы найти вкладки - если цель состоит в том, чтобы обрабатывать вкладки как часть большего сеанса сценариев, это не служит какой-либо полезной цели.
Вы можете использовать grep "$(echo -e '\t')"
Единственное требование - echo
быть способным интерпретировать обратную косую черту.
Эти альтернативные методы двоичной идентификации полностью функциональны. И мне очень нравится тот, кто использует awk, так как я не мог вспомнить использование синтаксиса с одиночными двоичными символами. Однако также должно быть возможно присвоить переменной оболочки значение в переносимом режиме POSIX (т.е. TAB = echo "@" | tr "\100" "\011"
), а затем использовать его отовсюду, в переносимом режиме POSIX; а также (т.е. имя файла grep "$ TAB"). Хотя это решение хорошо работает с TAB, оно также будет хорошо работать с другими двоичными символами, когда в назначении используется другое желаемое двоичное значение (вместо значения для символа TAB, равного 'tr').
Нотация $ '\ t', приведенная в других ответах, зависит от оболочки - похоже, она работает в bash и zsh, но не универсальна.
ПРИМЕЧАНИЕ: следующее для fish
оболочки и не работает в bash :
В fish
оболочке можно использовать без кавычек \t
, например:
grep \t foo.txt
Или можно использовать шестнадцатеричные или юникодные нотации, например:
grep \X09 foo.txt
grep \U0009 foo.txt
(эти обозначения полезны для более эзотерических символов)
Поскольку эти значения должны быть заключены в кавычки, можно объединить значения в кавычках и без кавычек путем объединения:
grep "foo"\t"bar"
Вы можете напечатать
grep \ t foo
grep '\ t' foo
искать символ табуляции в файле foo. Вы также можете использовать другие escape-коды, хотя я только протестировал \ n. Хотя это отнимает много времени и неясно, зачем вам это нужно, в zsh вы также можете ввести символ табуляции, вернуться к началу, grep и заключить вкладку в кавычки.
Ищите пробелы много раз [[: space:]] *
grep [[: space:]] * '.' '.'
Найдет что-то вроде этого:
«вкладка» ..
Это одинарные кавычки ('), а не двойные (").
Так вы делаете конкатенацию в grep. = -)
grep "<Ctrl+V><TAB>"
, это работает (если в первый раз: введите,grep "
затем нажмите комбинацию клавиш Ctrl + V, затем нажмите клавишу TAB, затем введите"
и нажмите Enter, вуаля!)