grep un onglet sous UNIX

418

Comment puis-je greptabuler (\ t) dans les fichiers sur la plate-forme Unix?

Sachin Chourasiya
la source
53
il suffit d'utiliser grep "<Ctrl+V><TAB>", cela fonctionne (si la première fois: tapez grep "puis appuyez sur la combinaison de touches Ctrl + V, puis appuyez sur la touche TAB, puis tapez "et appuyez sur Entrée, voilà!)
tour
16
ctrl + v est une IDÉE VRAIMENT MAUVAISE! ... oui, cela peut fonctionner à partir de la commande de la console, mais cela peut ne pas fonctionner pour le taper dans un script (vous êtes à la merci de l'éditeur, par exemple j'utilise mcedit et ctrl + v NE PAS y travailler)
THESorcerer
Connexes, mais pas en double: Recherche d'onglets, sans -P, en utilisant 'grep'
Peter Mortensen
Voir aussi: askubuntu.com/questions/53071/… (lié également ci-dessous)
shiri

Réponses:

375

Si vous utilisez GNU grep, vous pouvez utiliser l'expression rationnelle de style Perl:

grep -P '\t' *
se détendre
la source
Cela ne semble pas aller à l'encontre de mon modèle. Tenter d'utiliser cette syntaxe n'imprime rien. (La variante Mac OS X est-elle différente?)
futureelite7
2
@futureelite: Selon les documents d'Apple ( developer.apple.com/Mac/library/documentation/Darwin/Reference/… ), le programme grep de Mac OS X devrait prendre en charge l'option -P. Pensez à créer une nouvelle question sur superuser.com.
détendre le
3
C'est très bien pour GNU UNIX, mais qu'en est-il de POSIX Solaris, AIX et HP-UX? Ceux-là ne savent rien de l' -Poption.
tour
21
@rook GNU's Not UNIX.
Lily Chung
5
dans Mac OSX, vous pouvez donner un modèle en utilisant -e
Faisal Feroz
314

L'astuce consiste à utiliser $ sign avant les guillemets simples . Il fonctionne également pour les outils coupés et autres.

grep $'\t' sample.txt
antimirov
la source
7
La pointe de sauvetage sauve des vies! Cela fonctionne zshaussi bien, pour autant que je sache. Pourriez-vous commenter la sémantique de ce $signe?
Romain
2
Ne fonctionne pas si la chaîne contient autre chose que «\ t». Comment rechercheriez-vous "\ t" (tabulation + espace) par exemple?
Raman
6
Raman: Vous pouvez utiliser $'\t'' '. Un exemple réel qui montre que cela fonctionne également avec sh (pas seulement bash, qui n'est pas installé par défaut sur Android) est busybox grep -oE '^nodev'$'\t''fuse$' /proc/filesystems.
v6ak
5
Je pense que $ '...' est un idiome bash. Ne fonctionne probablement pas dans sh. Je ne sais pas pour csh ou tcsh.
Edward Falk
5
De 'man bash': les mots de la forme $ 'string' sont traités spécialement. Le mot se développe en chaîne, avec des caractères d'échappement antislash remplacés comme spécifié par la norme C ANSI. Les séquences d'échappement de
barre oblique inverse
84

Je n'ai jamais réussi à faire fonctionner le métacaractère '\ t' avec grep. Cependant, j'ai trouvé deux solutions alternatives:

  1. Utilisation <Ctrl-V> <TAB>(en appuyant sur Ctrl-V puis en tapant l'onglet)
  2. Utilisation de awk: foo | awk '/\t/'
SamK
la source
4
La | awk '/\t/'solution fonctionnera pour tous les shells, plates-formes et systèmes.
Samveen
6
+1 pour la solution POSIX portable et n'utilisant pas les bashismes, zshism, GNUism et linuxismes.
Jens
1
ctrl-V n'est pas utile si vous souhaitez copier-coller (à partir de vos notes ou d'un script). Mieux vaut utiliser une solution explicite qui a un '\ t' visible, les TAB littéraux (c'est-à-dire ceux qui ressemblent à des espaces) sont souvent convertis en SPC lors du copypasting ...
plijnzaad
awkfonctionne bien ici, mais dans certains tests sur ma machine avec de très gros fichiers, il est environ 30% plus lent que l'utilisation grep -P. Cela peut être trivial et non pertinent en fonction du cas d'utilisation, et awkpeut être meilleur simplement pour la lisibilité et la portabilité.
theferrit32
43

De cette réponse sur Ask Ubuntu:

Dites à grep d'utiliser les expressions régulières telles que définies par Perl (Perl a \tcomme onglet):

grep -P "\t" <file name>

Utilisez le caractère d'onglet littéral:

grep "^V<tab>" <filename>

Utilisez printfpour imprimer un caractère de tabulation pour vous:

grep "$(printf '\t')" <filename>
Caca
la source
1
Verbatim de http://askubuntu.com/a/53096/453741
villapx
ctrl-V n'est pas utile si vous souhaitez copier-coller (à partir de vos notes ou d'un script). Mieux vaut utiliser une solution explicite qui a un «\ t» visible, les TAB littéraux (c'est-à-dire ceux qui ressemblent à des espaces) sont souvent convertis en SPC lors du copypasting
plijnzaad
31

Une façon est (c'est avec Bash)

grep -P '\t'

-P active les expressions régulières Perl pour que \ t fonctionne.

En tant qu'utilisateur dérouleur dit, il peut être spécifique à GNU grep. L'alternative est d'insérer littéralement un onglet là-dedans si le shell, l'éditeur ou le terminal le permet.

tjmoore
la source
Option P inconnue dans le shell ksh
Sachin Chourasiya
Comme le dit le déroulement, peut être spécifique à GNU grep. Juste clarifié.
tjmoore
Comment ajoutez-vous un onglet? Ne démarre-t-il pas le processus de saisie automatique lorsque vous appuyez sur le bouton de tabulation? (cela pourrait fonctionner dans un script bash mais pas dans la ligne de commande)
AntonioCS
1
@AntonioCS comme indiqué ci-dessus par SamKrieg, afin que le shell vous permette de taper n'importe quel caractère, tapez d'abord CTRL-v. Voir aussi askubuntu.com/questions/53071/…
Denis Arnaud
2
-P est spécifique à grep, pas à n'importe quel shell. -P devrait fonctionner dans n'importe quel shell, à condition que GNU grep soit installé
plijnzaad
13

Une autre façon d'insérer l'onglet littéralement à l'intérieur de l'expression consiste à utiliser la $'\t'citation moins connue dans Bash:

grep $'foo\tbar'        # matches eg. 'foo<tab>bar'

(Notez que si vous correspondez à des chaînes fixes, vous pouvez l'utiliser avec le mode '-F'.)

Parfois, l'utilisation de variables peut rendre la notation un peu plus lisible et gérable:

tab=$'\t'               # `tab=$(printf '\t')` in POSIX
id='[[:digit:]]\+'
name='[[:alpha:]_][[:alnum:]_-]*'
grep "$name$tab$id"     # matches eg. `bob2<tab>323`
Alois Mahdal
la source
10

Ce n'est pas exactement ce que vous recherchez, mais pourrait fonctionner dans votre cas

grep '[[:blank:]]'

Équivalent à

grep -P '[ \t]'

Il trouvera donc Espace et Tab.

§ Classes de caractères

Remarque, il n'est pas annoncé dans mon man grep , mais fonctionne toujours

$ man grep | grep blanc | toilettes
      0 0 0
Steven Penny
la source
@ A-letubby Cela fonctionne maintenant avec l'édition - l' -Pargument a été ajouté.
villapx
6

Utilisez l'écho pour insérer l'onglet pour vous grep "$(echo -e \\t)"

vanjoe
la source
6

Il existe essentiellement deux façons de le résoudre:

  1. ( Recommandé ) Utilisez la syntaxe des expressions régulières prise en charge par grep (1). Grep (1) moderne prend en charge deux formes de syntaxe d'expression régulière POSIX 1003.2: les RE de base (obsolètes) et les RE modernes . La syntaxe est décrite en détail sur les pages de manuel re_format (7) et regex (7) qui font respectivement partie des systèmes BSD et Linux. GNU grep (1) prend également en charge les RE compatibles Perl comme fourni par la bibliothèque pcre (3).

    En langage regex, le symbole de tabulation est généralement codé par \tatome. L'atome est pris en charge par les expressions régulières étendues BSD ( egrep, grep -Esur un système compatible BSD), ainsi que par les RE compatibles Perl ( pcregrep, GNU grep -P).

    Les expressions régulières de base et les RE étendues Linux n'ont apparemment pas de support pour le \t . Veuillez consulter la page de manuel de l'utilitaire UNIX pour savoir quel langage regex il prend en charge (d'où la différence entre les expressions régulières sed (1), awk (1) et pcregrep (1)).

    Par conséquent, sous Linux:

    $ grep -P '\t' FILE ...
    

    Sur le système similaire à BSD:

    $ egrep '\t' FILE ...
    $ grep -E '\t' FILE ...
    
  2. Passez le caractère de tabulation dans le motif. Ceci est simple lorsque vous modifiez un fichier de script:

    # no tabs for Python please!
    grep -q '   ' *.py && exit 1
    

    Cependant, lorsque vous travaillez dans un shell interactif, vous devrez peut-être compter sur les capacités du shell et du terminal pour taper le symbole approprié dans la ligne. Sur la plupart des terminaux, cela peut être fait par une combinaison de touches Ctrl+ Vqui demande au terminal de traiter le caractère d'entrée suivant littéralement ( Vc'est pour "verbatim"):

    $ grep '<Ctrl>+<V><TAB>' FILE ...
    

    Certains shells peuvent offrir un support avancé pour la composition des commandes. Tels, en bash (1), les mots du formulaire $'string'sont traités spécialement:

    bash$ grep $'\t' FILE ...
    

    Veuillez noter cependant, tout en étant agréable dans une ligne de commande, cela peut générer des problèmes de compatibilité lorsque le script sera déplacé vers une autre plate-forme. Aussi, soyez prudent avec les citations lorsque vous utilisez les spéciaux, veuillez consulter bash (1) pour plus de détails.

    Pour le shell Bourne (et pas seulement), le même comportement peut être émulé en utilisant la substitution de commandes augmentée par printf (1) pour construire une expression rationnelle appropriée:

    $ grep "`printf '\t'`" FILE ...
    
Mike Volokhov
la source
4

grep "$(printf '\t')" travaillé pour moi sur Mac OS X

kumar303
la source
2

utilisez gawk, définissez le délimiteur de champ sur tab (\ t) et vérifiez le nombre de champs. Si plus de 1, alors il y a / sont des onglets

awk -F"\t" 'NF>1' file
ghostdog74
la source
2
C'est un peu exagéré et passe à côté de la question. awk /\t/est suffisant pour la question de l'op.
Expiation limitée
2

Un bon choix est d'utiliser 'sed as grep' (comme expliqué dans ce tutoriel sed classique ).

sed -n 's/pattern/&/p' file

Exemples (fonctionne en 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
Julio
la source
1

+1 façon, qui fonctionne dans ksh, dash, etc: utilisez printf pour insérer TAB:

grep "$(printf 'BEGIN\tEND')" testfile.txt
Zsigmond Lőrinczy
la source
Cela n'a pas fonctionné pour moi sur Ubuntu Trusty (Bash 4.3.11), ce qui suit a fonctionné cependant:grep "$(printf '\t')" testfile.txt
Josh Rumbut
0

La réponse est plus simple. Écrivez votre grep et dans la citation tapez la touche tab, cela fonctionne bien au moins en ksh

grep "  " *
YullyBear
la source
3
vous devez d'abord réussir à saisir un caractère TAB dans votre shell - la plupart des shells interprètent cette clé comme une commande (achèvement)
Kaii
0

Sur ksh j'ai utilisé

grep "[^I]" testfile
AIXroot
la source
0

Utiliser la méthode 'sed-as-grep', mais remplacer les onglets par un caractère visible de préférence personnelle est ma méthode préférée, car elle montre clairement à la fois quels fichiers contiennent les informations demandées et aussi où elles sont placées dans les lignes:

sed -n 's/\t/\*\*\*\*/g' file_name

Si vous souhaitez utiliser les informations de ligne / fichier ou d'autres options grep, mais souhaitez également voir le remplacement visible du caractère de tabulation, vous pouvez le faire en

grep -[options] -P '\t' file_name | sed 's/\t/\*\*\*\*/g'

Par exemple:

$ echo "A\tB\nfoo\tbar" > test
$ grep -inH -P '\t' test | sed 's/\t/\*\*\*\*/g'
test:1:A****B
test:2:foo****bar

EDIT: Évidemment, ce qui précède n'est utile que pour afficher le contenu du fichier pour localiser les onglets --- si l'objectif est de gérer les onglets dans le cadre d'une session de script plus grande, cela ne sert à rien.

Silasvb
la source
0

Cela fonctionne bien pour AIX. Je recherche des lignes contenantJOINED<\t>ACTIVE

voradmin cluster status | grep  JOINED$'\t'ACTIVE

 vorudb201   1       MEMBER(g) JOINED        ACTIVE
*vorucaf01   2       SECONDARY JOINED        ACTIVE
gruic
la source
0

Vous voudrez peut-être utiliser grep "$(echo -e '\t')"

La seule exigence echodoit être capable d'interpréter les échappements antislash.

kshpolvind
la source
0

Ces méthodes d'identification binaires alternatives sont totalement fonctionnelles. Et, j'aime vraiment celui qui utilise awk, car je ne me souviens pas vraiment de l'utilisation syntaxique avec des caractères binaires uniques. Cependant, il devrait également être possible d'attribuer une variable shell une valeur de manière portable POSIX (c'est-à-dire TAB = echo "@" | tr "\100" "\011"), puis de l'utiliser à partir de là partout, de manière portable POSIX; aussi (ie nom de fichier grep "$ TAB"). Bien que cette solution fonctionne bien avec TAB, elle fonctionnera également bien avec d'autres caractères binaires, lorsqu'une autre valeur binaire souhaitée est utilisée dans l'affectation (au lieu de la valeur du caractère TAB à «tr»).

odoncaoa
la source
0

La notation $ '\ t' donnée dans d'autres réponses est spécifique au shell - elle semble fonctionner en bash et zsh mais n'est pas universelle.

REMARQUE: ce qui suit concerne le fishshell et ne fonctionne pas dans bash :

Dans le fishshell, on peut utiliser un non cité \t, par exemple:

grep \t foo.txt

Ou on peut utiliser les notations hexadécimales ou unicode, par exemple:

grep \X09 foo.txt
grep \U0009 foo.txt

(ces notations sont utiles pour les caractères plus ésotériques)

Puisque ces valeurs doivent être non cotées, on peut combiner des valeurs cotées et non cotées par concaténation:

grep "foo"\t"bar"
Raman
la source
-4

Vous pouvez taper

grep \ t foo

ou

grep '\ t' foo

pour rechercher le caractère de tabulation dans le fichier foo. Vous pouvez probablement aussi faire d'autres codes d'échappement, même si je n'ai testé que \ n. Bien que cela prenne beaucoup de temps et que vous ne compreniez pas pourquoi vous le souhaitez, dans zsh, vous pouvez également taper le caractère de tabulation, retour au début, grep et entourez l'onglet de guillemets.

Saumure accidentelle
la source
-6

Recherchez plusieurs fois des espaces vides [[: space:]] *

grep [[: space:]] * '.' '.'

Trouvera quelque chose comme ceci:

'l'onglet' ..

Ce sont des guillemets simples (') et non doubles (").
C'est ainsi que vous effectuez la concaténation dans grep. = -)

Caio Argolo
la source