132 votes

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

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

IFS=$'\n'
  • Que fait le signe du dollar moyenne exactement ?
  • Que fait-il dans ce cas précis spécifique ?
  • 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 d'autre) ?

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

Par exemple, si je veux parcourir en boucle chaque ligne d'un fichier et que je souhaite utiliser une boucle for, je peux procéder comme suit :

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

Cependant, cela ne fonctionnera pas correctement à moins que IFS est défini comme un caractère de saut de ligne. Pour que ça marche, il faudrait que je fasse ça :

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 suis seulement curieux à ce sujet $'\n' et je me demandais si quelqu'un pouvait me donner une explication à ce sujet.

170voto

sepp2k Points 157757

Normalement bash n'interprète pas les séquences d'échappement dans les chaînes de caractères. Ainsi, 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 un backslash suivi de la lettre n (dans les deux autres cas).

$'somestring' es un syntaxe pour les chaînes de caractères avec des séquences d'échappement . Donc, contrairement à '\n' , $'\n' est en fait un saut de ligne.

2 votes

Pas exactement. \n est juste une lettre (échappée) n. Vous avez raison de dire que '\n' y "\n" sont des contretemps suivis de n.

15 votes

Notez que $'\n' est spécifique à bash -- il ne fonctionnera pas dans un shell POSIX ( /bin/sh ). Pour obtenir le même effet d'une manière conforme à POSIX, vous pouvez taper IFS=' puis appuyez sur la touche retour pour taper un véritable caractère de nouvelle ligne, puis tapez la fermeture '

23 votes

IFS=$(echo -e '\n') devrait également le faire d'une manière compatible avec POSIX.

24voto

mklement0 Points 12597

Pour donner à la construction son nom officiel : chaînes de caractères de la forme $'...' sont appelés Chaînes de caractères citées en ANSI C .

C'est-à-dire, comme dans les chaînes de caractères C [ANSI], séquences d'évitement du contrecoup sont reconnus et élargis à leur équivalent littéral (voir ci-dessous pour la liste complète des séquences d'échappement prises en charge).

Après cette expansion, $'...' se comportent de la même manière que les chaînes de caractères '...' chaînes de caractères - c'est à dire qu'ils sont traités comme des littéraux NON soumis à des expansions d'obus [supplémentaires]. .

Par exemple, $'\n' se développe en un caractère littéral de nouvelle ligne - ce qui est quelque chose qu'un littéral de chaîne de caractères bash normal (qu'il s'agisse de '...' ou "..." ) ne peuvent pas le faire. [1]

Une autre caractéristique intéressante est que Les chaînes citées en ANSI C peuvent échapper à ' (guillemets simples) comme \' qui, '...' (chaînes de caractères régulières entre guillemets) ne le 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 type backslash, si elles sont présentes, sont décodées comme suit :

\a alerte (cloche)

\b retour en arrière

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

\f flux de formulaires

\n nouvelle ligne

\r retour à la ligne

\t onglet horizontal

\v onglet vertical

\ barre oblique inversée

\' guillemet simple

\" double guillemet

\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/CEI 10646) dont la valeur est la valeur hexadécimale HHHHHHH (un à huit chiffres hexadécimaux)

\cx un caractère control-x

Le résultat développé est placé entre guillemets, comme si le signe dollar n'avait pas été présent.


[1] Vous pouvez toutefois intégrer réel les sauts de ligne dans les chaînes "..." et "..." ; autrement dit, vous pouvez définir des chaînes qui s'étendent sur plusieurs lignes.

16voto

Brad Swerdfeger Points 307

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

Les mots de la forme "$'STRING'" sont traités d'une manière particulière. Le mot se développe en une chaîne de caractères, avec les caractères échappés de l'antislash sont remplacés comme spécifié par la norme ANSI-C. Les séquences d'échappement de barres obliques inversées peuvent être dans la documentation de Bash.

Je suppose qu'il s'agit de forcer le script à échapper au saut de ligne selon la norme ANSI-C appropriée.

8voto

Marek Points 31

Récupération de l'IFS par défaut - ceci OLDIFS=$IFS n'est pas nécessaire. Exécutez le nouvel IFS dans un sous-shell pour éviter de remplacer l'IFS par défaut :

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

De plus, je ne crois pas vraiment que l'on puisse récupérer complètement l'ancien IFS. Vous devriez le mettre entre guillemets pour éviter les retours à la ligne, comme par exemple OLDIFS="$IFS" .

2 votes

C'est une technique vraiment utile. je viens de l'utiliser pour une opération de jointure de coquillages plus propre : args=$(IFS='&'; echo "$*") . rétablissement IFS à $' \t\n' d'une manière conviviale pour le Bourne Shell n'est pas une mince affaire.

1 votes

Re Besides I don't really believe you recover the old IFS fully Le dédoublement des mots est no sur le RHS des assignations de variables (mais la suppression des guillemets l'est), donc OLDIFS=$IFS y OLDIFS="$IFS" se comportent de la même manière.

3voto

Big Shield Points 197

Les chaînes citées en ANSI C sont un point clé. Merci à @mklement0 .

Vous pouvez tester les chaînes citées en 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

Sorties :

0000000  \n  
0000001

0000000   \   n   
0000002

0000000   \   n   
0000002

0000000   \   n   
0000002

Vous pouvez en connaître le sens clairement par les résultats.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X