Wie kann ich nach Tabulatoren suchen, ohne Literal-Tabulatoren zu verwenden, und warum funktioniert \ nicht?

146

Wenn ich mit (e) grep nach Registerkarten in einer Datei suche, verwende ich die Litteral-Registerkarte ( ^v + <tab>). Ich kann nicht \tals Ersatz für Tabulatoren in regulären Ausdrücken verwenden. Mit zB sed funktioniert dieser Ausdruck sehr gut.

Gibt es also eine Möglichkeit, einen nicht-literarischen Ersatz zu verwenden, <tab>und welche Hintergründe gibt es für einen nicht funktionierenden / nicht interpretierten \t?

Lasall
quelle

Antworten:

206

grep verwendet reguläre Ausdrücke gemäß POSIX . Aus welchen Gründen auch immer, POSIX wurde nicht \tals Registerkarte definiert .

Sie haben mehrere Alternativen:

  • weise grep an, die regulären Ausdrücke wie von perl definiert zu verwenden (perl hat \tals tab):

    grep -P "\t" foo.txt

    Die Manpage warnt, dass dies eine "experimentelle" Funktion ist. zumindest \tscheint es gut zu funktionieren. Fortgeschrittenere Perl-Regex-Funktionen jedoch möglicherweise nicht.

  • Verwenden Sie printf, um ein Tabulatorzeichen für Sie zu drucken:

    grep "$(printf '\t')" foo.txt
  • benutze das wörtliche Tabulatorzeichen:

    grep "^V<tab>" foo.txt

    das heißt: tippen grep ", dann drücken ctrl+v, dann drücken tab, dann tippen " foo.txt. Durch Drücken ctrl+vdes Terminals wird die nächste Taste wörtlich gedrückt. Dies bedeutet, dass das Terminal ein Tabulatorzeichen einfügt, anstatt eine an die Tabulatortaste gebundene Funktion auszulösen.

  • benutze die Ansi c Quoting Funktion von bash:

    grep $'\t' foo.txt

    Dies funktioniert nicht in allen Shells.

  • benutze awk:

    awk '/\t/'
  • benutze sed:

    sed -n '/\t/p'

Im Wikipedia-Artikel über reguläre Ausdrücke finden Sie eine Übersicht über die in POSIX und anderen Systemen definierten Zeichenklassen.

Lesmana
quelle
gestützt auf die antwort von enzotib möchte ich folgendes hinzufügen: grep $'\t' foo.txt(aber ich würde normalerweise schreiben fgrepanstatt grep)
Walter Tross
Ich brauchte dies, kombiniert mit dem Wert einer Umgebungsvariablen. Ich habe verwendet grep "$(printf '\t')${myvar}" foo.txt. Es hat gut funktioniert. Mit ein paar Versuchen konnte ich das letzte Formular nicht zum Laufen bringen.
sancho.s
1
Gibt es einen Grund, warum Plain grepnicht stillschweigend \tals Tab interpretiert werden kann? Bedeutet dies für POSIX \tetwas anderes? Vielleicht sollte es nur mit einem Literal \ gefolgt von einem übereinstimmen t?
Aaron McDaid
Vielleicht ist es erwähnenswert, dass BSD (einschließlich OSX) grep die Option -P fehlt.
TextGeek
Von der Manpage This is highly experimental and grep -P may warn of unimplemented features.Wahrscheinlich keine gute Idee, um -Pin Legacy-Systemen zu verwenden. Die printfWahl ist besser
Avindra Goolcharan
13

Es ist nicht genau die Antwort, die Sie hören möchten, aber eine mögliche Verwendung von Escape-Sequenzen bietet bash

command | grep $'\t'

(nicht in doppelte Anführungszeichen setzen!)

Enzotib
quelle
1
es besteht keine Notwendigkeit für das -E (was gesucht wird, ist kein regulärer Ausdruck). Es ist auch nicht erforderlich, einen Befehl weiterzuleiten. Das heißt, danke für den Hinweis auf diese ganz übersehen Merkmal bash (single-quoted Strings von $ voraus)
Walter Tross
2
In der Tat schlage ich vor, dass @enzotib die Antwort so bearbeitet, dass sie einfach ist grep $'\t'.
Teemu Leisti
Es sollte betont werden, dass dies eine Funktion von bash ist und (stillschweigend!) Das Falsche tut, wenn es von einer anderen Shell ausgeführt wird (z. B. dash, die die Standardeinstellung für Shell-Skripte unter Ubuntu und anderen ist)
xjcl
2

awk '/\t/' ist meine bevorzugte Problemumgehung:

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

Ausgang: a\t.

Ciro Santilli ist ein Schauspieler
quelle
1

Man kann immer darauf zurückgreifen, ASCII-Hex-Code für tab zu verwenden:

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

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

$ grep $'\x9' input.txt                                            
one two
Sergiy Kolodyazhnyy
quelle