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

12

Percebo que para definir nova linha IFSdeve com um $ como prefixo

IFS=$'\n'

mas se definir dois pontos, apenas

IFS=:

É \numa variável?

Cálculo
fonte

Respostas:

21

Que $'...'em bashnão é parâmetro de expansão, é um tipo especial de citação introduzido por ksh93que se expande aqueles \n, \x0a, \12códigos para um caractere de nova linha. zshtambém adicionado \u000a. ksh93e bashtambém tem \cjenquanto zshtem \C-J. ksh93também suporta variações como \x{a}.

O $é um sinal de que é alguma forma ou expansão. Mas em qualquer caso, difere de outras formas de expansões que o uso $(como $((1 + 1)), $paramou $(cmd)) na medida em que não é realizada dentro de aspas ou aqui documentos ( echo "$'x'"saídas $'x'em todas as conchas que não é especificado por POSIX) e sua expansão não está sujeita a cisão + glob, é definitivamente mais próximo de um operador de cotação do que de um operador de expansão.

IFS=\ndefiniria o IFS como n( \é tratado como um operador de citação) e IFS="\n"ou IFS='\n'definiria o IFS para a barra invertida de dois caracteres e n.

Você também pode usar:

IFS='
'

ou

IFS="
"

ou

IFS=$'
'

Para passar uma nova linha literal, embora isso seja menos legível (e não se pode ver à excepção de usar coisas como set listem vise $IFScontém outros caracteres de espaçamento nesse código).

IFS=:, IFS=':', IFS=":", IFS=$':'Tudo pronto IFS para :que ele não importa qual você usa.

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

As conchas ese fishtambém podem ser usadas \nfora das aspas para expandir para a nova linha.

Algumas ferramentas printf, algumas implementações echoou awktambém podem expandi-las \nsozinhas. Por exemplo, pode-se fazer:

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

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

IFS = $ (printf '\ n')

não funcionará porque o comando substitution ( $(...)) retira todos os caracteres de nova linha à direita. No entanto, você pode usar:

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

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

Agora, para completude, no rcshell e derivadas (como esou akanga), $'\n'é de fato a expansão dessa \nvariável (uma variável cujo nome é a sequência de dois caracteres \e n). Essas conchas não têm uma limitação no que personagens nomes de variáveis podem conter e só tem um tipo de aspas: '...'.

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

rcAs variáveis ​​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\001bar$

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

Stéphane Chazelas
fonte
1
+1para o nível desumano usual de conhecimento
Steven Penny
10

Esta é a citação ANSI-C :

Palavras da forma $'string'são tratadas especialmente. A palavra se expande para string, com caracteres de escape de barra invertida substituídos conforme especificado pelo padrão ANSI C.

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

Isso não tem relação com a expansão dos parâmetros do shell , apesar do uso de $.

Stephen Kitt
fonte
6

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

Eles permitem usar a maioria dos escapes em C, por exemplo, $'\u2345'e os escapes que também são suportados echo.

Observe que, se você não quiser (no caso de ksh93 ou bash) usar esse método de escape, ainda poderá usar:

IFS='
'

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

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

esperto
fonte
As $'...'expansões diferem das de echo. Eles são mais parecidos com os do argumento de formato printf. Pois echo, um 0 é necessário em \0123enquanto para $'...'e printfformato, \0123seria \012uma nova linha seguida por um 3. literal.
Stéphane Chazelas
1
Observe que a $'...'especificação ainda está sendo discutida. Ainda há várias questões a serem resolvidas com a redação atualmente proposta.
Stéphane Chazelas 26/10
IIRC, foi fechado, mas foi reaberto. Devido ao fato de ainda haver bastante tempo antes que se torne eficaz, não vejo um problema real com isso.
schily 26/10
1
Foi fechado, levantei várias objeções, foi reaberto, depois foi emendado, ainda existem vários problemas (a maioria sobre \uxxxxexpansão) e nenhuma solução à vista que pudesse acomodar as implementações existentes. Portanto, pode não ser a próxima versão do POSIX. Talvez eles possam deixar a \uxxxxexpansão de fora para o problema8, para que ainda possamos ter pelo menos $'\n'.
Stéphane Chazelas