'\ n' dans `IFS = $ '\ n' est une variable?

12

Je remarque que pour définir la nouvelle ligne IFSdevrait avec un préfixe $

IFS=$'\n'

mais si vous définissez deux points,

IFS=:

Est \n-ce une variable?

Calcul
la source

Réponses:

21

Ce $'...'en bashest pas le paramètre d' expansion, il est un type particulier de citation introduite par ksh93qui élargit les \n, \x0a, \12codes à un retour à la ligne. zshégalement ajouté \u000a. ksh93et bashont également \cjtout zsha \C-J. ksh93prend également en charge des variations comme \x{a}.

C'est $un indice qu'il s'agit d'une forme ou d'une expansion. Mais dans tous les cas, il diffère des autres formes d'extensions qui utilisent $(comme $((1 + 1)), $paramou $(cmd)) en ce qu'il n'est pas effectué dans des guillemets doubles ou ici des documents (les echo "$'x'"sorties $'x'dans tous les shells ne sont pas spécifiées par POSIX) et son expansion n'est pas sujette à division + glob, il est nettement plus proche d'un opérateur de cotation que d'un opérateur d'expansion.

IFS=\ndéfinirait IFS sur n( \est traité comme un opérateur de citation) et IFS="\n"ou IFS='\n'définirait IFS sur les deux caractères barre oblique inverse et n.

Vous pouvez aussi utiliser:

IFS='
'

ou

IFS="
"

ou

IFS=$'
'

Pour passer une nouvelle ligne littérale, bien que ce soit moins lisible (et on ne peut pas voir autre que d' utiliser des choses comme set listdans visi $IFScontient d' autres caractères d'espacement dans ce code).

IFS=:, IFS=':', IFS=":", IFS=$':'Tous ensemble IFS :il n'a pas d' importance que vous utilisez.

$'...'est supporté (avec des variations) par au moins: ksh93, zsh, bash, mksh, busybox sh, FreeBSD sh. ksh93et bashont également une $"..."forme de guillemets utilisée pour la localisation de texte, bien qu'elle soit rarement utilisée car elle est lourde à déployer et à utiliser de manière portable et fiable.

Les coquilles eset fishpeuvent également être utilisées en \ndehors des guillemets pour s'étendre à la nouvelle ligne.

Certains outils comme printf, certaines implémentations de echoou awkpeuvent également les étendre \npar eux-mêmes. Par exemple, on peut faire:

printf '\n'
awk 'BEGIN{printf "\n"}'
echo
echo '\n\c' # UNIX compliant echos only

à la sortie du caractère de nouvelle ligne, mais notez que:

IFS = $ (printf '\ n')

ne fonctionnera pas car la substitution de commande ( $(...)) supprime tous les caractères de nouvelle ligne à la fin. Vous pouvez cependant utiliser:

eval "$(printf 'IFS="\n"')"

Ce qui fonctionne parce que la sortie de printfse termine par un "caractère, pas une nouvelle ligne.

Maintenant, pour être complet, dans le rcshell et les dérivés (comme esou akanga), il $'\n'y a bien l'expansion de cette \nvariable (une variable dont le nom est la séquence de deux caractères \et n). Ces obus ne sont pas une limitation de ce que les caractères des noms de variables peuvent contenir et seulement un type de citations: '...'.

$ rc
; '\n' = (foo bar)
; echo $'\n'
foo bar
; echo $'\n'(1)
foo

rcles variables sont également toutes exportées vers l'environnement, mais au moins dans la variante Unix de rc, pour les noms de variables comme \n, la version de la variable d'environnement subit une forme d'encodage:

; env | grep foo | sed -n l
__5cn=foo\001bar$

( 0x5cétant la valeur d'octet de l'ASCII \; voyez également comment cette variable de tableau a été codée avec un octet 0x1 comme séparateur).

Stéphane Chazelas
la source
1
+1pour le niveau de connaissance inhumain habituel
Steven Penny
10

Voici la citation ANSI-C :

Les mots du formulaire $'string'sont traités spécialement. Le mot se développe en string, avec des caractères d'échappement antislash remplacés comme spécifié par la norme C ANSI.

Ainsi $'\n'est remplacé par une nouvelle ligne.

Ceci n'est pas lié à l' expansion des paramètres du shell , malgré l'utilisation de $.

Stephen Kitt
la source
6

Des chaînes comme $'\n'ont été introduites par ksh93et ne font actuellement pas partie de la norme POSIX.

Ils permettent d'utiliser la plupart des échappements de type C, par exemple $'\u2345'et les échappements qui sont également pris en charge par echo.

Notez que si vous n'aimez pas (en cas de ksh93 ou bash) utiliser cette méthode d'échappement, vous pouvez toujours utiliser:

IFS='
'

ce qui est équivalent mais plus difficile à lire.

BTW: Cette extension a déjà passé le comité standard POSIX, mais elle est prévue pour SUSv8 qui devrait apparaître pas avant l'an 2020 car nous devons d'abord travailler sur notre retard par rapport à la liste actuelle des bogues.

schily
la source
Les $'...'extensions diffèrent de celle de echo. Ils ressemblent plus à ceux de l'argument format de printf. Pour echo, un 0 est requis dans \0123tandis que pour $'...'et printfformat, \0123serait \012une nouvelle ligne suivie d'un littéral 3.
Stéphane Chazelas
1
Notez que la $'...'spécification est toujours en cours de discussion. Il reste plusieurs problèmes à résoudre avec le libellé actuellement proposé.
Stéphane Chazelas
IIRC, Il a été fermé mais a été rouvert. Étant donné qu'il reste encore beaucoup de temps avant qu'il ne devienne effectif, je ne vois pas de réel problème avec cela.
schily
1
Il a été fermé, j'ai soulevé plusieurs objections, il a été rouvert, il a ensuite été modifié, il y a encore plusieurs problèmes (la plupart concernant l' \uxxxxextension), et aucune résolution en vue qui pourrait accueillir les mises en œuvre existantes. Il est donc possible qu'il ne soit pas intégré dans la prochaine version POSIX. Peut-être qu'ils pourraient laisser l' \uxxxxexpansion hors de question8, afin que nous puissions avoir au moins $'\n'.
Stéphane Chazelas