Connaissez-vous bien bash?


Utilisez-vous la coque tous les jours? Prêt à résoudre certains problèmes logiques et à apprendre quelque chose de nouveau? Bienvenue au chat.

Certaines des tâches présentées ici n'apporteront pas de réels avantages, car elles affectent certains cas limites complexes. L'autre partie sera utile à ceux qui utilisent constamment le shell et lisent les scripts des autres.

Remarque: au moment de la rédaction, l'auteur a utilisé bash 4.4.12 (1) -release dans le sous-système Linux sur Windows 10. La complexité des tâches est différente.

Flux d'entrée / sortie


Tâche 1

$ cat 1 The cake is a lie! Wanted! Cake or alive $ cat 1 | head | tail | sed -e 's/alive/dead/g' | tee | wc -l > 1 

Combien de lignes seront dans le fichier 1 après la commande?

La réponse
1

Explication
Après avoir interprété la commande, mais avant d'exécuter tous les programmes, bash fonctionne avec les flux d'entrée / sortie spécifiés. Ainsi, le fichier 1 est effacé avant de démarrer le premier programme et cat ouvre le fichier déjà effacé.

Tâche 2

 $ cat file1 I love UNIX! $ cat file2 I don't like UNIX $ cat file1 <file2 

Qu'est-ce qui sera affiché à l'écran?

La réponse
I love UNIX!

Explication
Certains programmes martèlent stdin lorsque des fichiers sont spécifiés.

Tâche 3

 $ cat file Just for fun $ cat file 1>&2 2>/dev/null 

Qu'est-ce qui sera affiché à l'écran?

La réponse
Just for fun

Explication
Il existe une idée fausse selon laquelle la séquence 1>&2 redirige le premier thread vers le second, mais ce n'est pas le cas. Considérez l'équipe de la mission. Au début de l'interprétation de la commande entrée, la table de flux ressemble à ceci:
012
stdinstdoutstderr

bash détecte la séquence 1>&2 et copie le contenu de la cellule 2 dans la cellule 1:
012
stdinstderrstderr

Après avoir détecté la séquence 2>/dev/null interpréteur écrit la valeur dans la cellule 2, en laissant les autres cellules intactes:
012
stdinstderr/ dev / null

bash affiche également un flux d'erreurs, afin que nous trouvions le texte du fichier à l'écran.

Tâche 4
Comment envoyer la sortie stdout Ă  stderr, et la sortie stderr, au contraire, Ă  stdout?

La réponse
4>&1 1>&2 2>&4

Explication
Le principe est exactement le même que dans la tâche précédente. C'est pourquoi nous avons besoin d'un flux supplémentaire pour le stockage temporaire.

Exécutables


Tâche 5

Compte tenu du fichier test.sh

 #!/bin/bash ls $* ls $@ ls "$*" ls "$@" 

Les commandes suivantes sont exécutées:

 $ ls 1 2 3 test.sh $ ./test.sh 1 2 3 

Que produira le script?

La réponse
1 2 3
1 2 3
ls: cannot access '1 2 3': No such file or directory
1 2 3


Explication
Sans guillemets, les variables $ * et $ @ ne sont pas différentes et sont développées dans tous les arguments positionnels donnés du script, séparés par un espace. Entre guillemets, la méthode de divulgation change: $ * devient "$ 1 $ 2 $ 3" ​​et $ @ à son tour "$ 1" "$ 2" "$ 3". Le fichier «1 2 3» ne se trouvant pas dans le répertoire, ls affiche une erreur

Tâche 6

Dans le répertoire actuel, créez un fichier -c avec les autorisations de 755 et le contenu suivant:

 #!/bin/bash echo $1 

Remettez à zéro la variable $ PATH et essayez d'exécuter:

 $ PATH= $ -c "echo SURPRISE" 

Qu'est-ce qui sera affiché à l'écran? Que se passe-t-il si vous ressaisissez la dernière commande?

La réponse
La première fois sera affichée SURPRISE , la deuxième fois echo SURPRISE

Explication
Si PATH est vide, le shell commence à rechercher des fichiers dans le répertoire courant. -c est juste situé. Le fichier exécutable étant un fichier texte, la première ligne est lue sur le sujet de shebang. L'équipe est constituée selon le modèle:

 <shebang> <filename> <args> 

Ainsi, avant exécution, notre commande ressemble à ceci:

 /bin/bash -c "echo SURPRISE" 

Et, par conséquent, ce n'est absolument pas ce que nous voulions faire.

Si vous l'exécutez une deuxième fois, le shell récupérera des informations sur -c dans le cache et l'exécutera déjà correctement. La seule façon de vous protéger d'un tel effet inattendu est d'ajouter deux inconvénients au shebang.

Variables


Tâche 7

 $ ls file $ cat <$(ls) $ cat <(ls) 

Qu'est-ce qui sera affiché dans le premier et le deuxième cas?

La réponse
Le premier affichera le contenu du fichier, le second - le nom du fichier.

Explication
Dans le premier cas, la substitution est effectuée

 cat <file 

Dans le second cas, <(ls) sera remplacé par un canal nommé connecté par l'entrée à stdout ls et la sortie de stdin cat.

Après substitution, la commande prendra la forme:

 cat /dev/fd/xx 


Tâche 8

 $ TEST=123456 $ echo ${TEST%56} 

Qu'est-ce qui sera affiché à l'écran?

La réponse
1234

Explication
Avec un tel enregistrement, le modèle correspond (# - depuis le début de la variable; ## - avec avidité depuis le début de la variable;% - depuis la fin de la variable; %% - avec avidité depuis la fin de la variable) et est supprimé lors de la substitution. Le contenu de la variable reste intact. Ainsi, par exemple, il est pratique d'obtenir le nom de fichier sans l'extension.

 $ TEST=file.ext $ echo ${TEST%.ext} file 


Tâche 9

 $ echo ${friendship:-magic} 

Qu'est-ce qui sera affiché à l'écran?

La réponse
Si la variable d'amitié est définie, alors le contenu de la variable. Sinon, la magie.

Explication
Dans la documentation, cette magie est appelée "non définie ou nulle" et vous permet d'utiliser la valeur par défaut spécifiée d'une variable sur une seule ligne.

Ordre d'exécution


Tâche 10

 while true; false; do echo Success done 

Qu'est-ce qui sera affiché à l'écran?

La réponse
Rien

Explication
Les instructions while et if vous permettent de placer une séquence entière d'actions dans la condition, mais le résultat (code retour) ne sera pris en compte que dans la dernière commande. Comme c'est faux, la boucle ne commencera même pas.

Tâche 11

 $ false && true || true && false && echo 1 || echo 2 

Qu'est-ce qui sera affiché à l'écran?

La réponse
2

Explication
Ajoutez des parenthèses pour un ordre explicite et simplifiez la commande, en tenant compte du fait que seul le code retour de la dernière commande est pris en compte:

 ((((false && true) || true) && false) && echo 1) || echo 2 (((false || true) && false) && echo 1) || echo 2 ((true && false) && echo 1) || echo 2 (false && echo 1) || echo 2 false || echo 2 echo 2 


Les commentaires, suggestions et tâches supplémentaires sont les bienvenus dans les commentaires ou les MP.

Source: https://habr.com/ru/post/fr413935/


All Articles