Il semble y avoir une incohérence que je ne peux pas comprendre concernant le shell bash.
Si j'exécute:
ls;date;time
les résultats des trois requêtes sont présentés dans l'ordre.
Cependant, lors de l'échange de la date et de l'heure, un message d'erreur apparaît.
Donc, si j'exécute:
ls;time;date
le message d'erreur indique: bash: syntax error near unexpected token 'date'
.
Quelqu'un peut-il expliquer cela?
time;date
vsdate;time
. Cela semble être un problème avec le pipeline entrantbash
et le dernier caractère généré avec latime
sortie. Les résultats testés dans différents émulateurs de terminal sont les suivants: - [Bash] $ date; heure # [OK] $ heure; date # [ NotOK ] bash: erreur de syntaxe près du jeton inattendu `date '$ heure # seule erreur n'apparaît pas qu'il s'agit du résultat de n'importe quelle date. - [Csh] $ date; heure # [OK] $ heure; date # [OK] - [Tcsh] $ date; heure # [OK] $ heure; date # [OK] - [Ksh] $ date; heure # [ OK] $ heure; date # [OK]Réponses:
La
time
commande dans votre pipeline n'est pas le/usr/bin/time
binaire, mais le bashtime
intégré. Comparezman time
avechelp time
. L'erreur que vous voyez est que bash ne parvient pas à analysertime
l'argument de. Cela doit être présent ou être une nouvelle ligne. C'est une nouvelle ligne dans votre premier exemple mais absente dans le second.D'un autre côté, si vous deviez courir
ou
où les guillemets autour
'time'
révoquent son statut de mot réservé, alors bash n'a aucun problème à analyser la ligne. Il analyse maintenant trois commandes dans une liste, qu'il exécutera en séquence et/usr/bin/time
signalera une erreur d'utilisation dans les deux cas.Addenda
Il a été observé que, bien que
time ; date
génère une erreur,time ; ; date
ne le fait pas. L'explication probable est quetime ;
bash est interprété comme équivalent àtime <newline>
. L'expressiontime ; ; date
est ensuite analysée comme la liste detime ;
etdate
.Ceci est cohérent avec l'observation que
time ;
ettime ; ;
sont également légaux, le second étant analysé comme la liste singleton contenanttime ;
suivie du point-virgule facultatif autorisé après les listes.Donc, une autre façon d'expliquer pourquoi
time ; date
donne l'erreurbash: syntax error near unexpected token 'date'
est detime
consommer le point-virgule qui le séparedate
. Il ne peut le faire que parce qu'iltime
s'agit d'un mot réservé à bash.la source
time
est censé autoriser une commande NULL, et le point-virgule est censé délimiter les listes, donc IMO latime
commande ne doit pas "consommer" le point-virgule après. Les autres commandes intégrées (qui peuvent prendre des arguments) ne présentent pas ce type de comportement.time;date
va de même pour la syntaxe dans toute interprétation. Cependanttime ;
ettime ; ;
serait alors également illégal. Il peut être débattu sitime
le comportement de est un bogue ou simplement non documenté (il est cohérent en interne), mais un rapport de bogue serait certainement en place. Seriez-vous prêt à le déposer?time by itself can time a null command
, puis il le fait par$$ = make_simple_command (x, (COMMAND *)NULL);
. Quant au dépôt d'un bug, je ne suis pas sûr 8)time ; date
fonctionne dansksh93
etmksh
sans erreur, même s'ilksh
y a untime
mot - clé.Bash traite le intégré
time
comme un cas spécial lors de l'analyse des lignes de commande.Comme on peut le lire dans la page de manuel bash, la ligne telle qu'elle est tapée est d'abord divisée en une liste:
où un pipeline est:
ou dans notre cas, simplement:
c'est-à-dire si le temps est présent, alors la commande doit également être présente.
[Il y a un cas particulier qui permet
time
d'être suivi d'une nouvelle ligne, mais cela ne s'applique pas ici]Donc, dans notre cas, nous avons:
étant divisé en deux pipelines:
et le pipeline 1 n'est pas bien formé, car nous avons
time
sans commande. D'où l'erreur.Notez que la ligne de commande
time
ne fonctionne pas non plus ici:bash analyse cela comme prévu, en 2 pipelines:
et
/usr/bin/time
refuse ensuite d'exécuter sans argument. Notez que c'est une erreur de/usr/bin/time
pas une erreur de bash.La raison pour laquelle le back-tick fonctionne est que le back-tick cesse d'
time
être interprété comme un élément spécial dans le pipeline.c'est à dire avec le back-tick:
il est analysé comme deux pipelines:
N'oubliez pas qu'un pipeline, dans notre cas, c'est:
et le problème était que nous n'avions
time
pas de commande, ce qui n'est pas autorisé. Mais maintenant, nous avons simplement la commande:sans le précédent
time
, car les tics inversés signifient quetime
c'est interprété comme la commande, pas comme un mot précédent.Donc bash exécute alors sa commande interne
time
sans args, ce qui est accepté. Il ne produit aucune sortie et nous ne voyons aucune erreur.Notez que:
exécute en fait le résultat de la fonction
time
intégrée, c'est-à-dire qu'il exécute tout ce que la fonctiontime
intégrée produit sur stdout. Mais commetime
il n'écrit rien à lui seul, il semble fonctionner.Enfin, il a été noté que cela fonctionne:
ce que je ne peux pas expliquer, malheureusement :)
la source
;date
donnebash: syntax error near unexpected token ;
, maistime ;date
donnebash: syntax error near unexpected token date
, il semble donc que bash ne traite pas la commande après l'heure intégrée comme "; date". Fait intéressant,time ; ; date
fonctionne.'time'
il perd son sens de mot réservé. Le faire en arrière en le faisant s'exécuter dans un sous-shell dont la sortie est épissée dans la commande. Cela n'a rien à voir avec la discussion. En effet, votre exemple`time\';date
prouve le contraire de votre affirmation: cela devrait donner une erreur par votre raisonnement car/usr/bin/time
nécessite un argument. La raison pour laquelle ce n'est pas le cas, c'est que dans le sous-shell dans lequel il s'exécute, il est à nouveau le mot réservétime
.