Vous ne pouvez pas utiliser! $ Dans le script?


11

Je me demande simplement pourquoi cela ne fonctionne pas

#!/bin/bash 

ls /bin
ls !$

Je m'attends à courir ls /bindeux fois, mais le second soulève des erreurs comme cela !$n'a pas été interprété

Ai-je raté quelque chose ou !$travaillé uniquement en ligne de commande?

Je n'ai pas trouvé de partie pertinente dans man bash(sur mac)


9
Bien qu'il existe une solution, est-ce vraiment le meilleur moyen d'y parvenir dans un script? l'historique est désactivé par défaut pour une raison lorsque vous exécutez de manière non interactive - un long script va spammer le fichier .bash_history. Je ne dis pas que cela ne valait pas la peine de le demander, mais juste que si vous songez à l'utiliser dans un script, est-ce vraiment la meilleure façon?
flungo

Réponses:


26

L'historique et l'expansion de l'historique sont désactivés par défaut lorsque le shell s'exécute de manière non interactive.

Vous avez besoin:

#!/bin/bash 

set -o history
set -o histexpand

ls /bin
ls !$

ou:

SHELLOPTS=history:histexpand bash script.sh

cela affectera toutes les instances bash qui script.shpeuvent s'exécuter.


9
attention à SHELLOPTS, cela affectera celui bashqui s'exécute script.sh, mais aussi toutes les autres bashinstances qui script.shpourront éventuellement s'exécuter (comme les autres bashscripts ...).
Stéphane Chazelas

Et il n'affectera aucun autre exemple qui exécute votre script. bash
Blacklight Shining

Je pense que cette réponse s'améliorerait si le commentaire de @ StéphaneChazelas y était édité.
Oliphaunt - réintègre Monica le

7

La chose sensée à faire serait

ls /bin
ls $_

ou

set ls /bin
$*
$*

ou

c='ls /bin'
$c
$c

Avertissements: il convient de se rappeler que chacun de ces éléments comporte des pièges. La solution $ _ capture uniquement le dernier argument unique: donc ls foo bar$ _ ne contiendra que juste bar. L'une en utilisant setécrasera les arguments ( $1, $2, etc.). Et tout cela, comme écrit, fonctionnera, mais lorsqu'il est généralisé à des commandes plus complexes (où les échappements et les espaces sont importants), vous pouvez rencontrer des difficultés. Par exemple: ls 'foo bar'(où l'argument de chemin d'accès unique foo barcontient deux espaces ou plus, ou tout autre caractère d'espaces blancs) ne se comportera pas correctement dans aucun de ces exemples. Un échappement correct (éventuellement combiné avec une evalcommande), ou une utilisation à la "$@"place de $*, peut être nécessaire pour contourner ces cas.


1
+1 pour une réponse portable et n'abusant pas d'un bashisme destiné à faciliter l'utilisation interactive. (Soit dit en passant, le désir de bash d'étendre interactivement les points d'exclamation dans la configuration par défaut est quelque chose que je trouve contre-intuitif en tant qu'utilisateur d'autres shells, et contre - productif car cela me fout toujours quand j'essaie de faire une commande de shell compliquée).
mtraceur

Bien qu'écrit en ce moment, j'hésitais à lui donner le +1 en raison des problèmes que les scripteurs shell débutants auront probablement lorsqu'ils essaieront de le généraliser à des commandes plus complexes. J'ai suggéré une modification pour ajouter au moins un paragraphe de mise en garde expliquant les pièges possibles de celui-ci.
mtraceur

@mtraceur: ce n'est pas portable, ne fonctionne qu'en bash, zsh, ksh (si deux commandes ne sont pas sur la même ligne). Travailler en tiret, mksh uniquement lorsqu'il est interactif
cuonglm

@cuongim: Désolé, j'étais peut-être trop imprudent général. Le $_chemin n'est pas portable, vous avez raison. L' setapproche fonctionne dans un tableau de bord non interactif, et avec l' ${1+"$@"}astuce (plus l'alias global zsh) devrait être générale, bien que je me souvienne vaguement qu'il seta l'habitude de ne pas être parfaitement portable avec certains (anciens?) Shells. L'approche define-a-variable-holding-the-command-and-then-eval-it, en particulier en utilisant un échappement correct et une evalcommande réelle , est complètement portable en général pour autant que je sache.
mtraceur
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.