Pourquoi la commande pipe «l | grep ”1“ ”obtenez le mauvais résultat?

13

Comme l'illustre l'image, j'utilise lpour obtenir le fichier dans le dossier actuel. Et puis je veux obtenir le fichier avec un numéro 1, donc j'utilise le pipeet le grep.

Mais pourquoi le fichier 2et 22s'affichent-ils? Et quel est le 1;34m?

$ l
./ ../ 1 11 2 22
$ l | grep "1"
1;34m./ 1;32m../ 1 11 2 22

Mise à jour

J'ai déjà alias la commande ldans mon zshrcfichier.

 alias lsp="ls"
 alias ll='ls -alF'
 alias la='ls -A'
 alias l='ls -CF'
 alias ls="ls -alh --color"

Et voici le résultat de la typecommande:

>$ type ls
ls is an alias for ls -alh --color

> $ type l
l is an alias for ls -CF
Lee
la source
4
Veuillez ne pas publier de captures d'écran de texte. Copiez le texte ici et appliquez la mise en forme du code.
muru
@muru Je pense que vous vouliez demander la sortie du post de type -a l?
WinEunuuchs2Unix
@ WinEunuuchs2Unix ah, oui.
muru
@Lee puis-je vous demander de publier la sortie de la type lscommande s'il vous plaît? avez-vous modifié l' lsalias d'une manière ou d'une autre?
Sergiy Kolodyazhnyy
@Serg déjà mis à jour.
Lee

Réponses:

27

Tout d'abord, ce que vous essayez de faire l| grep <filename>est mauvais. Ne le fais pas. Voici pourquoi.

l la commande est vraiment un alias pour ls -CF

$ type -a l
l is aliased to `ls -CF'

Par défaut dans Ubuntu bash, lsest un alias de ls --color=auto. Comme l'a souligné Steeldriver dans les commentaires, il --color=autoest censé désactiver la colorisation. Dans votre cas spécifique, vous avez alias ls="ls -alh --color"et alias l="ls -CF", ce qui finit par être ls -alh --color -CF. Cette combinaison particulière de commutateurs envoie toujours une sortie colorisée sur un tuyau. Par exemple:

$ ls -alh --color -CF ~/TESTDIR | cat -A                                                                                 
^[[0m^[[01;34m.^[[0m/  ^[[01;34m..^[[0m/  1.txt  2.txt  3.txt  out.txt$

Remarquez comment les répertoires .et ..ont les mêmes séquences d'échappement.

Qu'est-ce-que tout cela veut dire

Cela signifie que lla liste colorisée des fichiers sortira en fonction du type de fichier. Le problème est que la colorisation se produit avec l'utilisation de séquences d'échappement . C'est ce que les 1:34mchoses sont - ce sont des séquences d'échappement pour des couleurs spécifiques.

Le problème principal est que l'analyse syntaxique lsconduit souvent à une sortie incorrecte et à des désastres dans les scripts, simplement parce que lspermet des séquences d'échappement comme expliqué précédemment et d'autres caractères spéciaux. Voir cet article pour plus d'informations: http://mywiki.wooledge.org/ParsingLs

Ce que vous devez faire:

Utilisez la findcommande:

bash-4.3$ ls
1.txt  2.txt  3.txt  out.txt
bash-4.3$ find . -maxdepth 1 -iname "*1*"
./1.txt

Vous pouvez faire quelque chose comme ça avec shell glob et la [[commande de test moderne :

bash-4.3$ for file in * ;do if [[ "$file" =~ "1"  ]] ;then echo "$file" ;fi ; done
1.txt

Ou peut-être utiliser python, qui a de bien meilleures capacités de gestion de nom de fichier que bashseul

bash-4.3$ python -c 'import os;print [f for f in os.listdir(".") if "1" in f ]'
['1.txt']

S'il n'est pas nécessaire de traiter la sortie de ls, un simple globbing avec lspeut également faire le travail. (Rappelez-vous, c'est uniquement pour afficher la liste des fichiers, pas pour la passer à un autre programme pour gérer le texte de sortie)

bash-4.3$ ls *1*
1.txt
Sergiy Kolodyazhnyy
la source
2
Je pense que la sortie ne sera colorisée dans un tuyau que si elle --color=alwaysest également spécifiée - soit dans le cadre de l'alias pour lou dans un alias précédent pour lslui-même (en remplaçant la valeur par défaut alias ls='ls --color=auto').
steeldriver
@steeldriver Bon point, mais n'est-ce pas le cas lsdans bash par défaut? type lsme donne que c'est un alias pourls --color=auto
Sergiy Kolodyazhnyy
1
Oui, c'est la valeur par défaut - mais autodésactive la couleur dans un tube AFAIK. Pour voir les séquences de couleurs ANSI, il doit avoir été changé en --color=always, soit dans l' lsalias , soit dans l' lalias
steeldriver
Oh, je vois ce que tu veux dire. C'est très étrange.
Sergiy Kolodyazhnyy
@steeldriver J'ai donc demandé à OP de publier ses alias, et apparemment ce qu'ils ont, à savoir ls --color, n'empêche pas la colorisation (testé moi-même aussi). Mis à jour ma réponse en conséquence
Sergiy Kolodyazhnyy
6

Vos commandes let lssont configurées en tant qu'alias.

Lorsque vous les exécutez, la sortie passe par grep "1"(en utilisant |) chaque ligne d'écran où 1apparaît s'affiche, avec la 1couleur rouge.

Parce que les noms de fichiers ., .., 2et 22apparaissent sur la même ligne d'écran, ils sont émis par grepaussi bien , mais ne semblent pas en rouge qui montre grepmatchs.

Il :34ms'agit d'une séquence d'échappement pour une couleur qui ne peint pas correctement. Basé sur votre question révisée avec la sortie de type -a let type -ail peut être reproduit dans mon système. S'il vous plaît noter que vous devez changer votre alias de --colorpour --color=auto:

Sortie couleur

couleur ls

WinEunuuchs2Unix
la source
Les 1:34mchoses ne sont pas de la corruption, ce sont des séquences d'échappement utilisées pour la colorisation du texte. Voir ma réponse sur cette partie;)
Sergiy Kolodyazhnyy
@Serg Merci. J'ai révisé en fonction de la question révisée OP avec des alias.
WinEunuuchs2Unix
1

Dans votre essai, vous appeliez votre lsalias, donc le 1;34mbruit similaire provenant de la coloration, et puisque le tuyau |reçoit tout cela sur la même ligne, il grepcorrespond au fichier 1de cette ligne et imprime par conséquent cette ligne. Voici ce que vous voyez à l'écran.

Lorsque vous faites des choses comme ça, il est toujours bon de revenir à la commande système avec 1 résultat par ligne.

Pour vous débarrasser des alias \ls, tapez simplement et utilisez l'option -1pour imprimer les résultats séparés par des sauts de ligne.

$ \ls -1 | grep "1"
1
11

Remarque: la méthode de barre oblique inverse fonctionne avec chaque commande, \commandappelle simplement la commande système sans biais.

pilko
la source