grep
semble cassé sur ma machine. La réinstallation n'aide pas. Un redémarrage n'aide pas. Les deux premières lignes créent un fichier contenant du texte arbitraire et l'entrée se termine par le caractère control-D.
ls -1
signifie liste dans une colonne. Un exemple suit ...
> cat > file0.txt
asdf
> cp file0.txt file1.txt
> ls -1
file0.txt
file1.txt
> ls -1 | grep f*
>
Avant de rencontrer ce problème, j'ai fait une erreur en invoquant grep avec une citation inégalée, mais je ne comprends pas comment ce problème peut survivre à un redémarrage.
Exemple de devis inégalé ...
ls -1 | grep 'file* | wc
Dans cet exemple, la liste des répertoires est dirigée vers grep qui dirige vers le programme de compteur de ligne, Word et octet wc
.
grep
n'utilisait en aucun cas la sortie de ls
.Lorsque vous exécutez grep f*
dans une situation où votre Shell se développe f*
à deux ou plusieurs arguments, grep
considère tous sauf un comme des noms de fichiers à ouvrir et à lire. Lorsque grep
lit à partir de fichiers nommés, son comportement par défaut de lecture à partir de l'entrée standard ne s'applique pas, il ne lit donc pas les données qui lui sont redirigées à partir d'une autre commande.
Votre programme grep
n'est pas interrompu et le comportement que vous avez observé est le comportement correct et attendu, c'est pourquoi la réinstallation de grep
et le redémarrage ne l'ont pas modifié. Les détails suivent.
grep f*
n'a pas transmis d'argument de f*
à grep.grep
n'a jamais vu le texte f*
. Comme Soren A dit , f*
est un glob. Les globes sont traités spécialement par votre Shell. Parce que f*
n'était pas entre guillemets , le Shell l'a développé dans les noms des fichiers du répertoire courant qui commencent par f
. Chacun de ces noms a été passé à grep
comme argument séparé. ( Ce type d'extension Shell est connu sous le nom de globbing, expansion de nom de fichier et expansion de nom de chemin.)
D'après votre description, il existe exactement deux fichiers qui correspondent à f*
glob: file0.txt
et file1.txt
. Comme ce sont les deux seuls fichiers du répertoire actuel dont les noms commencent par f
, les arguments de ligne de commande passés à grep
à partir de l'exécution de grep f*
sont exactement les mêmes que ceux qui lui ont été transmis lors de l'exécution de grep file0.txt file1.txt
. Si vous deviez ajouter d'autres fichiers de ce type dans le répertoire, alors grep f*
passerait plus que ces deux noms de fichiers comme arguments à grep
, mais file0.txt
et file1.txt
serait toujours inclus parmi eux.
ls
vers grep
, mais grep
n'a pas lu depuis le pipe.Un tuyau relie le sortie standard d'une commande au entrée standard de l'autre. Comme cat
et de nombreuses autres commandes, grep
accepte les entrées de deux manières:
Vous pouvez lui passer des noms de fichiers comme arguments de ligne de commande, et il lira ces fichiers. Le premier argument sans option de grep
est le modèle, mais les arguments sans option suivants sont traités comme des noms de fichiers à partir desquels les entrées seront prises.
(Vous n'essayez pas de passer plusieurs modèles à grep
, mais si vous l'étiez, vous pourriez utiliser le -e
option, dont l'opérande est toujours traité comme un motif.)
Vous ne pouvez passer aucun argument de nom de fichier, et il lira à partir de sa propre entrée standard. Il s'agit de la situation dans laquelle il est efficace de diriger vers grep
. Ce n'est que dans absence des arguments de nom de fichier que grep
lit du tout l'entrée standard.
C'est pourquoi il est possible d'utiliser grep
pour rechercher un ou plusieurs fichiers, sans qu'il bloque et n'attende que vous saisissiez l'entrée dans un terminal. Lorsque vous dirigez vers grep
, l'entrée supplémentaire qui n'aurait aucun sens pour grep
à utiliser provient de la commande sur le côté gauche du tuyau plutôt que de votre terminal. grep
ne l'utilise toujours pas, et c'est une bonne chose.
(Vous n'essayez pas de faire en sorte que grep
lise l'entrée standard en plus d'un ou plusieurs fichiers nommés, mais si vous l'étiez, vous pourriez lui transmettre le -
argument.)
Parce que vous avez deux fichiers dans le répertoire courant dont les noms commencent par f
, le glob f*
se développe en deux arguments. La première, file0.txt
, est utilisé comme modèle . La deuxième, file1.txt
, est utilisé pour nommer un fichier d'entrée. Étant donné que grep
reçoit un argument spécifiant un fichier d'entrée, la première des deux situations décrites ci-dessus s'applique ("Vous pouvez lui passer des noms de fichiers comme arguments de ligne de commande"). Ainsi, grep
ne lit jamais depuis l'entrée standard et n'utilise jamais la sortie de ls
.
L'expression grep f*
sera, dans votre cas, étendu à grep file0.txt file1.txt
par le Shell.
Apparemment, il n'y a pas de ligne avec file0.txt
dans le fichier file1.txt.
Je sais que ce n'est pas ce que tu voulais, mais c'est comme ça que ça marche.
:~$ mkdir test
:~$ cd test/
:~/test$ touch f1
:~/test$ touch f2
:~/test$ set -x
:~/test$ ls | grep f*
+ ls --color=auto
+ grep --color=auto f1 f2
ls | grep 'f*'
est de mauvaise forme.
ls f*
devrait être préféré.
Lorsque vous utilisez des modèles d'expression régulière plus complexes, passez à egrep
/grep -E
.
Pendant que je suis ici, cat
est rarement nécessaire. tac
est 100 fois plus utile que cat
. cat
l'abus est un problème sérieux sur les systèmes de type Unix. ;)
*
est un caractère spécial qui est vaguement interprété comme une nouvelle commande/instruction. Vous souhaitez placer un \
devant:
ls -1 | grep f\*
Cependant, ce que vous voulez probablement, c'est obtenir tous les fichiers commençant par f
au lieu de TOUS les fichiers contenant un f
alors utilisez plutôt un autre caractère spécial:
ls -1 | grep ^f
Le ^
demande à grep de trouver les lignes commençant par f
.