Comment puis-je grep
tabuler (\ t) dans les fichiers sur la plate-forme Unix?
Comment puis-je grep
tabuler (\ t) dans les fichiers sur la plate-forme Unix?
Réponses:
Si vous utilisez GNU grep, vous pouvez utiliser l'expression rationnelle de style Perl:
grep -P '\t' *
-P
option.
L'astuce consiste à utiliser $ sign avant les guillemets simples . Il fonctionne également pour les outils coupés et autres.
grep $'\t' sample.txt
zsh
aussi bien, pour autant que je sache. Pourriez-vous commenter la sémantique de ce $
signe?
$'\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
.
Je n'ai jamais réussi à faire fonctionner le métacaractère '\ t' avec grep. Cependant, j'ai trouvé deux solutions alternatives:
<Ctrl-V> <TAB>
(en appuyant sur Ctrl-V puis en tapant l'onglet)foo | awk '/\t/'
| awk '/\t/'
solution fonctionnera pour tous les shells, plates-formes et systèmes.
awk
fonctionne 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 awk
peut être meilleur simplement pour la lisibilité et la portabilité.
De cette réponse sur Ask Ubuntu:
Dites à grep d'utiliser les expressions régulières telles que définies par Perl (Perl a
\t
comme onglet):grep -P "\t" <file name>
Utilisez le caractère d'onglet littéral:
grep "^V<tab>" <filename>
Utilisez
printf
pour imprimer un caractère de tabulation pour vous:grep "$(printf '\t')" <filename>
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.
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`
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.
Remarque, il n'est pas annoncé dans mon man grep
, mais fonctionne toujours
$ man grep | grep blanc | toilettes 0 0 0
-P
argument a été ajouté.
Il existe essentiellement deux façons de le résoudre:
( 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 \t
atome. L'atome est pris en charge par les expressions régulières étendues BSD ( egrep
, grep -E
sur 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 ...
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
+ V
qui demande au terminal de traiter le caractère d'entrée suivant littéralement ( V
c'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 ...
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
awk /\t/
est suffisant pour la question de l'op.
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
+1 façon, qui fonctionne dans ksh, dash, etc: utilisez printf pour insérer TAB:
grep "$(printf 'BEGIN\tEND')" testfile.txt
grep "$(printf '\t')" testfile.txt
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 " " *
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.
Vous voudrez peut-être utiliser grep "$(echo -e '\t')"
La seule exigence echo
doit être capable d'interpréter les échappements antislash.
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»).
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 fish
shell et ne fonctionne pas dans bash :
Dans le fish
shell, 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"
Vous pouvez taper
grep \ t foo
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.
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. = -)
grep "<Ctrl+V><TAB>"
, cela fonctionne (si la première fois: tapezgrep "
puis appuyez sur la combinaison de touches Ctrl + V, puis appuyez sur la touche TAB, puis tapez"
et appuyez sur Entrée, voilà!)