$ _ vs! $. Dernier argument de la commande précédente et redirection de sortie

28

La question concerne les variables spéciales. La documentation dit:

!!:$

désigne le dernier argument de la commande précédente . Cela peut être raccourci à! $.


( $_, un trait de soulignement.) Au démarrage du shell, définissez le chemin d'accès absolu utilisé pour appeler le shell ou le script de shell en cours d'exécution tel que transmis dans l'environnement ou la liste d'arguments. Par la suite, se développe jusqu'au dernier argument de la commande précédente après l'expansion. Définissez également le chemin d'accès complet utilisé pour appeler chaque commande exécutée et placée dans l'environnement exporté vers cette commande.

Il doit y avoir une différence que je ne peux pas attraper, car:

$ echo "hello" > /tmp/a.txt
$ echo "!$"
echo "/tmp/a.txt"
/tmp/a.txt

$ echo "hello" > /tmp/a.txt
$ echo $_
hello

Quelle est la différence?

Métier à tisser
la source
4
! $ est une extension de l'historique, pas une variable spéciale, donc je suppose que le code bash les gère différemment.
Jeff Schaller
2
Je n'ai pas de réponse définitive à cette question, mais: ① Le langage shell Bourne est l'un des, peut - être , le langage de programmation le moins cohérent en interne encore largement utilisé aujourd'hui. Tenter de déduire des principes généraux ne vous mènera nulle part. Il vous suffit de mémoriser toutes les règles spéciales. Désolé. ② Notez les mots "après expansion", immédiatement après la phrase que vous avez mise en évidence, dans la définition de $_. C'est crucial. Cela peut ne pas expliquer la différence qui vous intrigue, mais cela explique un tas d'autres façons $_et !$ne sont pas les mêmes.
2016

Réponses:

32

!$est un désignateur de mot de l'expansion de l'histoire, il se développe jusqu'au dernier mot de la commande précédente de l' histoire . IOW, le dernier mot de l'entrée précédente dans l'histoire. Ce mot est généralement le dernier argument à commander, mais pas en cas de redirection. Dans:

echo "hello" > /tmp/a.txt

toute la commande 'echo "hello" > /tmp/a.txt'est apparue dans l'histoire et /tmp/a.txtest le dernier mot de cette commande.

_est un paramètre shell, il se développe jusqu'au dernier argument de la commande précédente. Ici, la redirection ne fait pas partie des arguments passés à la commande, donc seul hellol'argument est passé à echo. C'est pourquoi $_étendu à hello.

_n'est plus l'un des paramètres spéciaux standard du shell . Il fonctionne bash, zsh, mkshet dashque lorsque interactive, ksh93que lorsque deux commandes sont sur des lignes séparées:

$ echo 1 && echo $_
1
/usr/bin/ksh

$ echo 1
1
$ echo $_
1
cuonglm
la source
1
Un effet de l' !$expansion par rapport au $_paramètre est qu'il echo $_apparaît toujours dans l'historique comme echo $_, tandis qu'il echo !$montre la valeur à laquelle il a été étendu. Par exemple, echo one twopuis echo !$, en appuyant sur les spectacles echo two.
Jacktose