web-dev-qa-db-fra.com

Quelle est la signification exacte de IFS = $ '\ n'?

Si l'exemple suivant, qui définit la variable d'environnement IFS sur un caractère de saut de ligne ...

IFS=$'\n'
  • Qu'est-ce que le signe dollar signifie exactement?
  • Que fait-il dans ce cas particulier?
  • Où puis-je en savoir plus sur cet usage spécifique (Google n'autorise pas les caractères spéciaux dans les recherches et je ne sais pas quoi chercher autrement)?

Je sais ce qu'est la variable d'environnement IFS et ce que la \n caractère est (saut de ligne), mais pourquoi ne pas simplement utiliser la forme suivante: IFS="\n" (qui ne fonctionne pas)?

Par exemple, si je souhaite parcourir toutes les lignes d'un fichier et utiliser une boucle for, je peux le faire:

for line in (< /path/to/file); do
    echo "Line: $line"
done

Cependant, cela ne fonctionnera pas correctement à moins que IFS soit défini sur un caractère de saut de ligne. Pour que cela fonctionne, je devrais faire ceci:

OLDIFS=$IFS
IFS=$'\n'
for line in (< /path/to/file); do
    echo "Line: $line"
done
IFS=$OLDIFS

Note: Je n'ai pas besoin d'un autre moyen pour faire la même chose, j'en connais déjà beaucoup d'autres ... Je ne suis curieux que de cela $'\n' et je me demandais si quelqu'un pourrait me donner une explication à ce sujet.

115
Yanick Girouard

Normalement, bash n'interprète pas les séquences d'échappement dans les littéraux de chaîne. Donc, si vous écrivez \n ou "\n" ou '\n', ce n'est pas un saut de ligne - c'est la lettre n (dans le premier cas) ou une barre oblique inverse suivie de la lettre n (dans les deux autres cas).

$'somestring' est un syntaxe pour les littéraux de chaîne avec des séquences d'échappement. Donc, contrairement à '\n', $'\n' est en fait un saut de ligne.

155
sepp2k

Juste pour donner à la construction son nom officiel : chaînes de la forme $'...' sont appelés chaînes citées par ANSI C.

C’est-à-dire que, comme dans les chaînes C [ANSI], , les séquences d'échappement à jeu inversé sont reconnues et étendues à leur équivalent littéral (voir ci-dessous la liste complète des séquences d'échappement prises en charge).

Après cette extension, $'...' Les chaînes se comportent de la même manière que '...' chaînes - c’est-à-dire qu’elles sont traitées comme littéraux NON soumises à toute [autre] expansion du shell .

Par exemple, $'\n' se développe en un caractère de nouvelle ligne littéral - qui est un littéral de chaîne bash classique (que '...' ou "...") ne peut pas faire.[1]

Une autre caractéristique intéressante est que les chaînes citées par ANSI C peuvent échapper à ' (guillemets simples) comme \', qui, '...' _ (chaînes simples, entre guillemets) ne peuvent pas:

echo $'Honey, I\'m home' # OK; this cannot be done with '...'

Liste des séquences d'échappement prises en charge :

Les séquences d'échappement de barre oblique inverse, le cas échéant, sont décodées comme suit:

\ une alerte (cloche)

\ b retour arrière

\ e\E un caractère d'échappement (pas ANSI C)

\ f form feed

\ n newline

\ r retour chariot

\ t onglet horizontal

\ v onglet vertical

\ backslash

\' simple citation

\" double citation

\ nnn le caractère de huit bits dont la valeur est la valeur octale nnn (un à trois chiffres)

\ xHH le caractère de huit bits dont la valeur est la valeur hexadécimale HH (un ou deux chiffres hexadécimaux)

\ uHHHH le caractère Unicode (ISO/IEC 10646) dont la valeur est la valeur hexadécimale HHHH (un à quatre chiffres hexadécimaux)

\ UHHHHHHHH le caractère Unicode (ISO/IEC 10646) dont la valeur est la valeur hexadécimale HHHHHHHH (un à huit chiffres hexadécimaux)

\ cx un caractère de contrôle-x

Le résultat étendu est indiqué entre guillemets simples, comme si le signe dollar n'avait pas été présent.


[1] Vous pouvez toutefois intégrer actuel newlines dans les chaînes '...' et "..."; c'est-à-dire que vous pouvez définir des chaînes qui s'étendent sur plusieurs lignes.

18
mklement0

De http://www.linuxtopia.org/online_books/bash_guide_for_beginners/sect_03_03.html :

Les mots sous la forme "$ 'STRING'" sont traités de manière particulière. Word se développe en une chaîne, avec des caractères d'échappement avec une barre oblique inversée remplacés comme spécifié par la norme ANSI-C. Des séquences d'échappement avec une barre oblique inverse peuvent être trouvées dans la documentation Bash.

Je suppose que cela force le script à échapper le saut de ligne au standard ANSI-C approprié.

16
Brad Swerdfeger

Re récupérer le IFS par défaut - this OLDIFS=$IFS n'est pas nécessaire. Exécutez le nouvel IFS dans le sous-shell pour éviter de remplacer l'IFS par défaut:

ar=(123 321); ( IFS=$'\n'; echo ${ar[*]} )

En outre, je ne crois pas vraiment que vous récupériez complètement le vieil IFS. Vous devriez le citer deux fois pour éviter les sauts de ligne tels que OLDIFS="$IFS".

8
Marek

La chaîne ANSI C-cotée est un point clé. Merci à @ mklement0.

Vous pouvez tester les chaînes citées par ANSI C avec la commande od.

echo -n $'\n' | od -c
echo -n '\n' | od -c
echo -n $"\n" | od -c
echo -n "\n" | od -c

Les sorties:

0000000  \n  
0000001

0000000   \   n   
0000002

0000000   \   n   
0000002

0000000   \   n   
0000002

Vous pouvez connaître le sens clairement par les sorties.

3
Big Shield