'\ n' em 'IFS = $' \ n 'é uma variável?

12

Noto que para definir a nova linha IFS deve com um prefixo $ as

IFS=$'\n'

mas se definir dois pontos, apenas

IFS=:

\n é uma variável?

    
por JawSaw 26.10.2018 / 14:32

3 respostas

21

Esse $'...' em bash não é expansão de parâmetro, é um tipo especial de cotação introduzido por ksh93 que expande os códigos \n , \x0a , para um caractere de nova linha. zsh também adicionou \u000a . ksh93 e bash também têm \cj , enquanto zsh tem \C-J . ksh93 também suporta variações como \x{a} .

O $ é uma sugestão de que é alguma forma ou expansão. Mas em qualquer caso, ele difere de outras formas de expansões que usam $ (como $((1 + 1)) , $param ou $(cmd) ), pois não é executado dentro de aspas duplas ou aqui documentos ( echo "$'x'" outputs $'x' em todos os shells, embora não seja especificado por POSIX) e sua expansão não está sujeita a split + glob, é definitivamente mais próxima de um operador de cotação do que de um operador de expansão.

IFS=\n definiria o IFS como n ( \ é tratado como um operador de cotação) e IFS="\n" ou IFS='\n' configuraria o IFS para as barras invertidas de dois caracteres e n .

Você também pode usar:

IFS='
'

ou

IFS="
"

ou

IFS=$'
'

Para passar uma nova linha literal, embora seja menos legível (e não se pode ver nada além de usar coisas como set list in vi se $IFS contiver outros caracteres de espaçamento nesse código).

IFS=: , IFS=':' , IFS=":" , IFS=$':' todos definem o IFS como : , portanto, não importa qual você usar.

$'...' é suportado (com variações) por pelo menos: ksh93 , zsh , bash , mksh , busybox sh , FreeBSD sh . ksh93 e bash também têm uma forma de aspas $"..." usada para localização de texto, embora raramente seja usada, pois é difícil de implantar e usar de maneira portável e confiável.

As conchas es e fish também podem usar \n fora das cotações para expandir para a nova linha.

Algumas ferramentas como printf , algumas implementações de echo ou awk também podem expandir essas \n por si mesmas. Por exemplo, pode-se fazer:

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

para a saída do caractere de nova linha, mas observe que:

IFS=$(printf '\n')

não funcionará porque a substituição de comando ( $(...) ) retira todos os caracteres de nova linha à direita. Você pode no entanto usar:

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

O que funciona porque a saída de printf termina em um caractere " , não em uma nova linha.

Agora, para conclusão, no rc shell e derivados (como es ou akanga ), $'\n' é de fato a expansão dessa variável \n (uma variável cujo nome é a sequência de dois caracteres \ e n ). Essas shells não têm uma limitação em quais caracteres os nomes das variáveis podem conter e possuem apenas um tipo de aspas: '...' .

$ rc
; '\n' = (foo bar)
; echo $'\n'
foo bar
; echo $'\n'(1)
foo
As variáveis

rc também são exportadas para o ambiente, mas pelo menos na variante Unix de rc , para nomes de variáveis como \n , a versão da variável de ambiente passa por uma forma de codificação:

; env | grep foo | sed -n l
__5cn=foo
IFS='
'
1bar$

( 0x5c sendo o valor de byte de ASCII \ ; veja também como essa variável de matriz foi codificada com um byte 0x1 como o separador).

    
por 26.10.2018 / 14:37
10

Isso é citações ANSI-C :

Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.

Assim, $'\n' é substituído por uma nova linha.

Isso não está relacionado a expansão de parâmetros do shell , apesar do uso de $ .

    
por 26.10.2018 / 14:36
6

Strings como $'\n' foram introduzidas por ksh93 e atualmente não fazem parte do padrão POSIX.

Eles permitem usar a maioria dos escapes semelhantes, por exemplo $'\u2345' e as fugas que também são suportadas por echo .

Note que se você não gosta (no caso de ksh93 ou bash) de usar esse método de escape, você ainda pode usar:

IFS='
'

que é equivalente, mas mais difícil de ler.

BTW: Esta extensão já passou pelo comitê padrão POSIX, mas está programada para o SUSv8 que deve aparecer antes do ano de 2020, porque precisamos primeiro trabalhar em nosso atraso atrás do atual lista de bugs.

    
por 26.10.2018 / 14:43

Tags