GNU/Linux >> Tutoriels Linux >  >> Linux

Expansion de chaîne entre guillemets et non entre guillemets ?

  1. for i in $(xrandr); do echo "$i" ; done
  2. for i in "$(xrandr)"; do echo "$i"; done
  3. for i in "$(xrandr)"; do echo $i; done

Je comprends pourquoi 1 diffère de 2. Mais pourquoi 3 donne-t-il une sortie différente de 2 ? Veuillez également expliquer la sortie. Comment fonctionnent les guillemets sur les retours à la ligne ?

Réponse acceptée :

Une variable sans guillemets (comme dans $var ) ou substitution de commande (comme dans $(cmd) ou `cmd` ) est le split+glob opérateur dans les coques de type Bourne.

C'est-à-dire que leur contenu est divisé en fonction de la valeur actuelle du $IFS variable spéciale (qui contient par défaut les caractères espace, tabulation et saut de ligne)

Et puis chaque mot résultant de ce fractionnement est soumis à la génération du nom de fichier (également connu sous le nom de globbing ou expansion du nom de fichier ), c'est-à-dire qu'ils sont considérés comme des modèles et sont étendus à la liste des fichiers correspondant à ce modèle.

Donc dans for i in $(xrandr) , le $(xrandr) , car il n'est pas entre guillemets, est divisé en séquences d'espaces, de tabulations et de sauts de ligne. Et chaque mot résultant de ce fractionnement est vérifié pour les noms de fichiers correspondants (ou laissé tel quel s'ils ne correspondent à aucun fichier), et for les boucle tous.

Dans for i in "$(xrandr)" , nous n'utilisons pas l'opérateur split+glob comme substitution de commande est entre guillemets, il y a donc une passe dans la boucle sur une value :la sortie de xrandr (sans les caractères de fin de ligne qui substitution de commande bandes).

Cependant dans echo $i , $i est à nouveau sans guillemets, donc à nouveau le contenu de $i est divisé et soumis à la génération du nom de fichier et ceux-ci sont passés en tant qu'arguments séparés au echo commande (et echo affiche ses arguments séparés par des espaces).

Donc leçon apprise :

  • si vous ne voulez pas séparer les mots ou génération de nom de fichier , mettez toujours entre parenthèses les développements de variables et les substitutions de commandes
  • si vous voulez séparer les mots ou génération de nom de fichier , laissez-les sans guillemets mais définissez $IFS en conséquence et/ou activer ou désactiver la génération du nom de fichier si nécessaire (set -f , set +f ).

Typiquement, dans votre exemple ci-dessus, si vous voulez boucler sur la liste de mots séparés par des blancs dans la sortie de xrandr , vous devez :

  • laisser $IFS à sa valeur par défaut (ou annulez-la) pour diviser sur des blancs
  • Utilisez set -f pour désactiver la génération de nom de fichier sauf si vous êtes sûr que xrandr ne produit jamais de * ou ? ou [ caractères (qui sont des caractères génériques utilisés dans les modèles de génération de noms de fichiers)
Connexe :Db2 - trouver la chaîne de connexion pour une base de données DB2 ?

Et puis n'utilisez que l'opérateur split + glob (ne laissez que la substitution de commande ou l'expansion de variable sans guillemets) dans le in partie du for boucle :

set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done

Si vous voulez boucler sur les lignes (non vides) du xrandr sortie, vous devez définir $IFS au caractère de saut de ligne :

IFS='
'

Linux
  1. Comment remplacer une chaîne dans un ou plusieurs fichiers ?

  2. Expansion et variables des accolades Bash ?

  3. Comment diviser une chaîne dans un script bash

  4. in_addr_t à la chaîne

  5. utiliser random pour générer une chaîne aléatoire dans bash

Chaînes de concaténation bash

Comment vérifier si une chaîne contient une sous-chaîne dans Bash

Remplacement de chaîne dans Bash

Script Bash - Manipulation de chaînes

Ajouter une nouvelle ligne à la chaîne, multiplateforme

limite de longueur de chaîne de fonction system()