Comment faire pour grep pour les onglets sans utiliser les onglets littéraux et pourquoi cela ne fonctionne pas?

146

Lorsque je recherche des onglets dans un fichier avec (e) grep, j'utilise l'onglet littéral ( ^v + <tab>). Je ne peux pas utiliser \ten remplacement des tabulations dans les expressions régulières. Avec par exemple sed cette expression fonctionne très bien.

Donc, est-il possible d'utiliser un remplacement non littéral pour <tab>et quels sont les fonds pour un non-travail / non interprété \t?

Lasall
la source

Réponses:

206

grep utilise des expressions régulières définies par POSIX . Pour quelque raison que ce soit, POSIX n'a ​​pas défini \tcomme tab

Vous avez plusieurs alternatives:

  • Dites à grep d'utiliser les expressions régulières définies par perl (perl a \tpour tabulation):

    grep -P "\t" foo.txt

    la page de manuel indique qu'il s'agit d'une fonctionnalité "expérimentale". au moins \tsemble bien fonctionner. mais les fonctionnalités plus avancées de perl regex pourraient ne pas l'être.

  • utilisez printf pour imprimer un caractère de tabulation pour vous:

    grep "$(printf '\t')" foo.txt
  • utilisez le caractère de tabulation littéral:

    grep "^V<tab>" foo.txt

    c'est-à-dire: tapez grep ", puis appuyez sur ctrl+v, puis appuyez sur tab, puis tapez " foo.txt. en appuyant ctrl+vdans le terminal, la prochaine clé sera prise mot pour mot. cela signifie que le terminal insérera un caractère de tabulation au lieu de déclencher une fonction liée à la touche de tabulation.

  • utilisez la fonction de citation ansi c de bash:

    grep $'\t' foo.txt

    cela ne fonctionne pas dans tous les coquillages.

  • utiliser awk:

    awk '/\t/'
  • utiliser sed:

    sed -n '/\t/p'

Consultez l' article de Wikipédia sur les expressions régulières pour obtenir une vue d'ensemble des classes de caractères définies dans POSIX et d'autres systèmes.

lesmana
la source
En me basant sur la réponse de enzotib, permettez-moi d'ajouter ce qui suit: grep $'\t' foo.txt(mais j'écrirais habituellement à la fgrepplace de grep)
Walter Tross le
J'avais besoin de cela, combiné à l'utilisation de la valeur d'une variable d'environnement. J'ai utilisé grep "$(printf '\t')${myvar}" foo.txt. Cela a bien fonctionné. Avec quelques essais, je ne pouvais pas obtenir le dernier formulaire pour travailler.
Samedi
1
Y a-t-il une raison que plain grepne pourrait pas interpréter silencieusement \tcomme onglet? POSIX exige-t-il que \tcela veuille dire autre chose? Peut-être est-ce supposé correspondre à un littéral \ suivi d'un t?
Aaron McDaid
A noter que grep BSD (y compris OSX) n’a pas l’option -P.
TextGeek
Extrait de la page de manuel This is highly experimental and grep -P may warn of unimplemented features.Probablement pas une bonne idée à utiliser -Pdans les systèmes hérités. Le printfchoix est meilleur
Avindra Goolcharan
13

Ce n'est pas exactement la réponse que vous voudriez entendre, mais bash fournit une possibilité d'utilisation de séquences d'échappement.

command | grep $'\t'

(ne le mettez pas entre guillemets!).

enzotib
la source
1
il n'y a pas besoin de -E (ce qui est recherché n'est pas une regex). Il n'est pas non plus nécessaire de canaliser à partir d'une commande. Ceci dit, merci d'avoir signalé cette caractéristique assez négligée de bash (chaînes entre guillemets simples précédées de $)
Walter Tross le
2
En effet, je suggère que @enzotib édite la réponse simplement grep $'\t'.
Teemu Leisti
Il convient de souligner qu'il s'agit d'une fonctionnalité de bash et qu'il fera (en silence!) La mauvaise chose s'il est exécuté par un autre shell (tel que dash, qui est la valeur par défaut pour les scripts de shell sous Ubuntu et autres)
xjcl
2

awk '/\t/' est ma solution préférée:

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

Sortie: a\t.

Ciro Santilli 改造 心心
la source
1

On peut toujours avoir recours à l’ascii hex-code pour onglet:

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

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

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