Les scripts shell sont souvent utilisés comme colle, pour l'automatisation et les tâches ponctuelles simples. Quelles sont certaines de vos fonctionnalités "cachées" préférées du Bash Shell/langage de script?
Voir également:
insérer le dernier paramètre de la ligne précédente
alt-. la combinaison de touches la plus utile de tous les temps, essayez-la et voyez, pour une raison quelconque, personne ne la connaît.
appuyez encore et encore pour sélectionner les derniers paramètres les plus anciens.
génial quand vous voulez faire autre chose à quelque chose que vous avez utilisé il y a un instant.
Si vous souhaitez continuer à exécuter un processus après votre déconnexion:
disown -h <pid>
est un bash utile intégré. Contrairement à Nohup
, vous pouvez exécuter disown
sur un processus déjà en cours d'exécution.
Tout d'abord, arrêtez votre travail avec control-Z, obtenez le pid de ps
(ou utilisez echo $!
), utilisez bg
pour l'envoyer en arrière-plan, puis utilisez disown
avec l'indicateur -h.
N'oubliez pas d'arrière-plan votre travail ou il sera tué lorsque vous vous déconnecterez.
Presque tout ce qui est répertorié dans la section EXPANSION du manuel
En particulier, l'expansion des paramètres:
$ I=foobar
$ echo ${I/oo/aa} #replacement
faabar
$ echo ${I:1:2} #substring
oo
$ echo ${I%bar} #trailing substitution
foo
$ echo ${I#foo} #leading substitution
bar
Mon préféré:
Sudo !!
Réexécutez la commande précédente avec Sudo.
Ctrl + r commence une "recherche incrémentielle inversée" dans l'historique de vos commandes. Au fur et à mesure que vous tapez, il récupère la commande la plus récente qui contient tout le texte que vous entrez.
Tab complète le mot que vous avez tapé jusqu'à présent s'il n'est pas ambigu.
TabTab répertorie toutes les réalisations pour le mot que vous avez tapé jusqu'à présent.
Alt + * insère toutes les complétions possibles, ce qui est particulièrement utile, par exemple, si vous venez de saisir une commande potentiellement destructrice avec des caractères génériques:
rm -r source/d*.c
Alt + *rm -r source/delete_me.c source/do_not_delete_me.c
Ctrl + Alt + e effectue l'alias, l'historique et l'expansion de Shell sur la ligne actuelle. En d'autres termes, la ligne actuelle est ré-affichée car elle sera traitée par le Shell:
ls $HOME/tmp
CtrlAlt + els -N --color=tty -T 0 /home/cramey
Récupérer l'historique des commandes et des arguments
Il est possible d'accéder sélectivement aux commandes et arguments précédents en utilisant le !
opérateur. C'est très utile lorsque vous travaillez avec de longs chemins.
Vous pouvez vérifier vos dernières commandes avec history
.
Vous pouvez utiliser les commandes précédentes avec !<n>
étant n
l'index de la commande dans history
, les nombres négatifs comptent à rebours depuis la dernière commande de l'historique.
ls -l foo bar
touch foo bar
!-2
Vous pouvez utiliser les arguments précédents avec !:<n>
, zéro est la commande,> = 1 sont les arguments.
ls -l foo
touch !:2
cp !:1 bar
Et vous pouvez combiner les deux avec !<n>:<m>
touch foo bar
ls -l !:1 !:2
rm !-2:1 !-2:2
!-2
Vous pouvez également utiliser des plages d'arguments !<n>:<x>-<y>
touch boo far
ls -l !:1-2
Autre !
les modificateurs spéciaux sont:
*
pour tous les arguments
ls -l foo bar
ls !*
^
pour le premier argument (!:1
== !^
)
$
pour le dernier argument
ls -l foo bar
cat !$ > /dev/null
J'aime la fonction -x, qui permet de voir ce qui se passe dans votre script.
bash -x script.sh
SECONDS=0; sleep 5 ; echo "that took approximately $SECONDS seconds"
SECONDES
Chaque fois que ce paramètre est référencé, le nombre de secondes écoulées depuis l'appel du shell est renvoyé. Si une valeur est affectée à SECONDS, la valeur renvoyée lors des références suivantes est le nombre de secondes écoulées depuis l'affectation plus la valeur affectée. Si SECONDS n'est pas défini, il perd ses propriétés spéciales, même s'il est réinitialisé par la suite.
Voici l'un de mes favoris. Cela définit l'achèvement de l'onglet pour ne pas respecter la casse. C'est vraiment génial pour taper rapidement des chemins de répertoire, en particulier sur un Mac où le système de fichiers n'est pas sensible à la casse par défaut. Je mets ça dans .inputrc
dans mon dossier personnel.
set completion-ignore-case on
La variable spéciale aléatoire:
if [[ $(($RANDOM % 6)) = 0 ]]
then echo "BANG"
else
echo "Try again"
fi
CtrlxCtrle
Cela chargera la commande actuelle dans l'éditeur défini dans la variable VISUAL. C'est vraiment utile pour les commandes longues comme certaines de celles listées ici.
Pour utiliser vi comme éditeur:
export VISUAL=vi
Gestion des expressions régulières
Les versions récentes de bash proposent une correspondance d'expressions régulières, vous pouvez donc:
if [[ "mystring" =~ REGEX ]] ; then
echo match
fi
où REGEX est une expression régulière brute au format décrit par man re_format.
Les correspondances de toutes les parties entre crochets sont stockées dans le tableau BASH_REMATCH, en commençant à l'élément 1 (l'élément 0 est la chaîne correspondante dans son intégralité), vous pouvez donc l'utiliser pour effectuer également une analyse basée sur des expressions rationnelles.
Correction rapide et sale des fautes de frappe (particulièrement utile pour les commandes longues sur des connexions lentes où l'utilisation de l'historique des commandes et le défilement seraient horribles):
$ cat /proc/cupinfo
cat: /proc/cupinfo: No such file or directory
$ ^cup^cpu
Essayez aussi !:s/old/new
qui remplace une fois l'ancien par le nouveau dans la commande précédente.
Si vous souhaitez remplacer plusieurs occurrences, vous pouvez effectuer une substitution globale avec !:gs/old/new
.
Vous pouvez utiliser les commandes gs
et s
avec n'importe quel événement d'historique, par exemple.
!-2:s/old/new
Pour remplacer old
par new
(une fois) dans l'avant-dernière commande.
Voici deux de mes favoris:
Pour vérifier la syntaxe sans vraiment exécuter le script, utilisez:
bash -n script.sh
Revenez au dernier répertoire (oui je connais pushd et popd, mais c'est plus rapide)
cd -
Tableaux:
#!/bin/bash
array[0]="a string"
array[1]="a string with spaces and \"quotation\" marks in it"
array[2]="a string with spaces, \"quotation marks\" and (parenthesis) in it"
echo "There are ${#array[*]} elements in the array."
for n in "${array[@]}"; do
echo "element = >>${n}<<"
done
Plus de détails sur les tableaux (et autres trucs de script bash avancés) peuvent être trouvés dans le Advanced Bash-Scripting Guide .
man
:Ctrl + a et Ctrl + e déplacez le curseur au début et à la fin de la ligne actuelle, respectivement.
Ctrl + t et Alt + t transposez le caractère et le mot avant le curseur avec celui en cours, puis déplacez le curseur vers l'avant.
Alt + u et Alt + l convertir le mot actuel (du curseur à la fin) en majuscules et minuscules.
Indice: Appuyez sur Alt + – suivi par l'une de ces commandes pour convertir le début du mot actuel.
man
conseils:Lors de la visualisation des pages man
, utilisez / pour rechercher du texte dans les pages. Utilisation n pour passer au match suivant ou N pour le match précédent.
Accélérez votre recherche d'une commande ou d'une sous-section particulière dans les pages man
en profitant de leur mise en forme:
o Au lieu de taper /history expansion pour trouver cette section, essayez /^history, à l'aide du curseur (^
) pour rechercher uniquement les lignes qui commencent par "historique".
o Essayez / read, avec quelques espaces de début, pour rechercher cette commande intégrée. Les builtins sont toujours en retrait dans les pages man
.
tilisation des opérateurs booléens Infix
Considérez le simple si:
if [ 2 -lt 3 ]
then echo "Numbers are still good!"
fi
Ça a l'air un peu moche. Pas très moderne. Si vous utilisez des crochets doubles autour de votre expression booléenne, vous pouvez utiliser les opérateurs booléens normaux!
if [[ 2 < 3 ]]
then echo "Numbers are still good!"
fi
Exécution d'une commande avant d'afficher l'invite bash
Définissez une commande dans la variable env "Prompt_COMMAND" et elle sera exécutée automatiquement avant chaque invite. Exemple:
[lsc@home]$ export Prompt_COMMAND="date"
Fri Jun 5 15:19:18 BST 2009
[lsc@home]$ ls
file_a file_b file_c
Fri Jun 5 15:19:19 BST 2009
[lsc@home]$ ls
Pour les imbéciles d'avril suivants, ajoutez "export Prompt_COMMAND = cd" au .bashrc de quelqu'un, puis asseyez-vous et regardez la confusion se dérouler.
Vous pouvez ignorer certains fichiers lors de la finalisation de l'onglet en définissant la variable _ FIGNORE
.
Par exemple, si vous avez un référentiel de sous-versions et que vous souhaitez naviguer plus facilement,
export FIGNORE=".svn"
vous pouvez maintenant cd
sans être bloqué par .svn
répertoires.
export TMOUT=$((15*60))
Arrêtez bash après 15 minutes d'inactivité, réglé sur 0 pour le désactiver. Je mets généralement ceci dans ~/.bashrc sur mes comptes root. C'est pratique lors de l'administration de vos box et vous pouvez oublier de vous déconnecter avant de vous éloigner du terminal.
C-S--Control Shift Minus Annule les actions de frappe.
Toute opération de suppression C-w (supprimer le mot précédent), C-k (supprimer jusqu'à la fin de la ligne), C-u (supprimer au début de la ligne) etc ... copie son texte supprimé dans le kill ring, vous pouvez coller le dernier kill avec: C-y et parcourez (et collez) l'anneau des éléments supprimés avec Alt-y
Expansion du corset
Expansion standard avec {x, y, z}:
$ echo foo{bar,baz,blam}
foobar foobaz fooblam
$ cp program.py{,.bak} # very useful with cp and mv
Extension de séquence avec {x..y}:
$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo {a..f}{0..3}
a0 a1 a2 a3 b0 b1 b2 b3 c0 c1 c2 c3 d0 d1 d2 d3 e0 e1 e2 e3 f0 f1 f2 f3
Utilisation de l'arithmétique:
if [[ $((2+1)) = $((1+2)) ]]
then echo "still ok"
fi
Un autre petit: Alt+#
commente la ligne actuelle et la déplace dans le tampon d'historique.
Ainsi, lorsque vous assemblez une ligne de commande et que vous devez émettre une commande intermédiaire, par exemple trouver un fichier, vous appuyez simplement sur alt + #, lancez l'autre commande, remontez dans l'historique, décommentez et continuez.
Pas vraiment une fonctionnalité mais plutôt une direction: j'ai trouvé de nombreuses "fonctionnalités cachées", des secrets et diverses utilités bash sur commandlinefu.com . Beaucoup des réponses les mieux notées à ces réponses, je les ai apprises sur ce site :)
Accolades au lieu de do
et done
dans la boucle
For
le corps de la boucle est généralement dans do...done
(juste un exemple):
for f in *;
do
ls "$f";
done
Mais nous pouvons utiliser un style C en utilisant des accolades:
for f in *; {
ls "$f";
}
Je pense que cela semble mieux que do...done
et je préfère celui-ci. Je n'ai encore trouvé cela dans aucune documentation Bash, c'est donc vraiment une fonctionnalité cachée.
J'ai récemment lu la programmation Csh considérée comme nuisible qui contenait ce joyau étonnant:
Considérez le pipeline:
A | B | C
Vous voulez connaître le statut de C, eh bien, c'est simple: c'est en $ ?, ou $ status en csh. Mais si vous le voulez de A, vous n'avez pas de chance - si vous êtes dans le csh, bien sûr. Dans le Bourne Shell, vous pouvez l'obtenir, bien que cela soit un peu délicat. Voici quelque chose que j'ai dû faire lorsque j'ai exécuté le stderr de dd dans un tube grep -v pour se débarrasser du bruit d'entrée/sortie des enregistrements, mais j'ai dû retourner l'état de sortie du dd, pas celui de grep:
device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;
Tronquer le contenu d'un fichier (fichier de mise à zéro)
> file
Plus précisément, cela est très bon pour tronquer les fichiers journaux, lorsque le fichier est ouvert par un autre processus, qui peut toujours écrire dans le fichier.
Expressions numériques de style C:
let x="RANDOM%2**8"
echo -n "$x = 0b"
for ((i=8; i>=0; i--)); do
let n="2**i"
if (( (x&n) == n )); then echo -n "1"
else echo -n "0"
fi
done
echo ""
Ces propriétés sont un autre de mes favoris.
export HISTCONTROL=erasedups
export HISTSIZE=1000
Le premier s'assure que bash n'enregistre pas les commandes plus d'une fois, améliorera vraiment l'utilité de history
. L'autre étend la taille de l'historique à 1000 par rapport à la valeur par défaut de 100. J'ai en fait défini cette valeur à 10000 sur mes machines.
Se déplacer facilement entre plusieurs répertoires
Pas une fonctionnalité cachée, mais beaucoup plus flexible que pushd qui nécessite une navigation de type pile.
a() { alias $1=cd\ $PWD; }
cd
quelque part et tapez a 1
. Plus tard, il suffit de taper 1
retournera dans ce répertoire.
set -o vi
afin d'avoir une édition de type vi de l'historique des commandes ainsi que de la commande actuellement tapée.
Celui que j'utilise beaucoup est! $ Pour faire référence au dernier mot de la dernière commande:
$ less foobar.txt
...
# I dont want that file any more
$ rm !$
J'ai un alias r='fc-s'
, et je le trouve très utile dans certains cas limités. Pour exécuter la dernière commande, tapez simplement r
et appuyez sur Entrée, et c'est tout. Bien sûr, cela n'est pas très utile car la flèche vers le haut fait la même chose. Mais vous pouvez utiliser r
pour exécuter la commande précédente avec des substitutions. Disons que votre dernière commande était une longue commande compilant un fichier:
$ gcc -c <file_name>.c <lots of options> -o <file_name>.o
Vous voulez maintenant compiler un autre fichier avec les mêmes options et avoir un .o
fichier:
$ r <file_name>=<new_file>
le fera. Vous n'avez pas besoin d'utiliser la flèche vers le haut, de naviguer aux bons endroits, puis de les remplacer manuellement chacun. Cela peut être répété plusieurs fois, vous pouvez donc le faire ensuite:
$ r <new_file>=<other_file>
Bien sûr, pour une telle chose, vous avez des makefiles, mais j'espère avoir montré que l'alias est utile.
Je n'ai pas eu besoin de beaucoup de cet alias, mais il y a eu des moments où je suis content d'avoir cet alias!
Comme d'autres l'ont mentionné, Ctrl-r est idéal pour revenir en arrière dans l'historique de vos commandes. Mais que se passe-t-il si vous voulez avancer après avoir fait un ou plusieurs pas de trop? C'est là que Ctrl-s est très pratique. Cependant, il est normalement mappé sur XOFF (interruption du flux de données). Comme ce n'est plus trop utile parce que nous n'utilisons pas de terminaux série lents, vous pouvez désactiver ce mappage avec:
stty -ixon
dans ton ~/.bashrc
fichier.
Cela fait également Ctrl-q disponible qui est normalement un double de Ctrl-v (entre guillemets qui vous permet d'insérer un caractère de contrôle littéral). j'ai Ctrl-q mappé à menu-complete qui parcourt les complétions lorsqu'il est pressé à plusieurs reprises. J'aime partir Tab réglé sur régulier complet.
Vous pouvez définir Ctrl-q au menu complet en ajoutant cette ligne à votre ~/.inputrc
fichier:
"\C-q": menu-complete
ici les chaînes (<<<
). Le manuel Bash donne cette description:
Le mot est développé et fourni à la commande sur son entrée standard.
Exemple:
$ cat<<<"$(( 10*3+1 )) Nice isn't it?"
31 Nice isn't it?
Bash a une indirection variable:
$ foo=bar
$ baz=foo
$ echo ${!baz}
bar
Noms de fichiers de socket spéciaux:/dev/tcp/Host/PORT et/dev/udp/Host/PORT
Lire à partir d'un serveur de jour (port 13):
$ cat < /dev/tcp/utcnist.colorado.edu/13
55786 11-08-13 03:34:21 50 0 0 172.3 UTC(NIST) *
Cela peut être très utile en conjonction avec tcpserver .
Un exemple plus avancé de http://thesmithfam.org/blog/2006/05/23/bash-socket-programming-with-devtcp-2/ si vous n'avez pas accès à wget ou boucle:
$ exec 3<>/dev/tcp/www.google.com/80 # hook up to file desc 3
$ echo -e "GET / HTTP/1.1\n\n" >&3 # send the HTTP request
$ cat <&3 # read the HTTP response
Substitution de processus avec <(cmd ...) ou> (cmd ...)
Dans chaque formulaire, le cmd est exécuté avec son entrée ou sa sortie connectée à un FIFO, et le chemin d'accès à celui-ci FIFO est substitué sur la ligne de commande:
$ echo A file to read: <(cat), a file to write to: >(cat)
A file to read: /dev/fd/63, a file to write to: /dev/fd/62
Par exemple, pour comparer deux sites Web sans enregistrer de fichiers intermédiaires:
$ diff <(curl -s http://tldp.org/LDP/abs/html/) <(curl -s http://www.redhat.com/mirrors/LDP/LDP/abs/html/)
Si vous avez une commande qui prend un nom de fichier en entrée, mais n'accepte pas "-" pour signifier stdout, vous pouvez le tromper:
$ do_thingee --log -
error: can't open log file: '-'
$ do_thingee --log >(cat)
do_thingee v0.2
initializing things
processing 4 things
done
tilisation de la commande bash intégrée 'let' pour l'arithmétique de base
A=10
let B="A * 10 + 1" # B=101
let B="B / 8" # B=12, let does not do floating point
let B="(RANDOM % 6) + 1" # B is now a random number between 1 and 6
Pour effectuer des évaluations en virgule flottante, vous pouvez utiliser la commande "bc" (aucune partie de bash).
FP=`echo "scale=4; 10 / 3" | bc` # FP="3.3333"
Obtenez plus d'informations sur les combinaisons de touches dans Bash dans http://linuxconfig.net/manual-howto/key-combinations-in-bash.html
Substitution de commande intégrée:
nom d'hôte && Dig + short $ (nom d'hôte) && Dig + short -x $ (Dig + short $ (nom d'hôte))
Cette commande est utile pour vérifier RDNS sur votre serveur de messagerie. : P
Recherche rapide dans l'historique
Ce qui suit donne une recherche d'historique comme tcsh qui est pratique et plus facile.
Ajoutez les lignes suivantes à ~/.inputrc
ou /etc/inputrc
.
$ cat ~/.inputrc
"\e[A": history-search-backward
"\e[B": history-search-forward
Vous souhaiterez peut-être utiliser une combinaison de touches moins accidentelle telle que Esc
+ p
. Si tel est le cas, utilisez
"\ep": history-search-backward
"\en": history-search-forward
Ensuite, tapez simplement les premières lettres et appuyez sur la touche Flèche haut. Il montrera la commande la plus récente qui commence par les lettres données.
ex:
tapez grep
, UpArrow. Cela montrera quelque chose comme grep -ri myText .