'\ n' en `IFS = $ '\ n' es una variable?

12

Me doy cuenta de que para establecer nueva línea IFSdebe tener un prefijo $ como

IFS=$'\n'

pero si establece dos puntos, solo

IFS=:

¿ \nEs una variable?

Cálculo
fuente

Respuestas:

21

Que $'...'en bashno es el parámetro de expansión, que es un tipo especial de cotización introducida por ksh93que expande los \n, \x0a, \12códigos a un carácter de nueva línea. zshTambién añadido \u000a. ksh93y bashtambién tiene \cjmientras zshtiene \C-J. ksh93También admite variaciones como \x{a}.

El $es una señal de que es alguna forma o expansión. Pero en cualquier caso, difiere de otras formas de expansión que usan $(como $((1 + 1)), $paramo $(cmd)) en que no se realiza entre comillas dobles o aquí documentos (las echo "$'x'"salidas $'x'en todos los shells, aunque no están especificadas por POSIX) y su expansión no está sujeta a división + glob, definitivamente está más cerca de un operador de cotizaciones que de un operador de expansión.

IFS=\nestablecería IFS en n( \se trata como un operador de cotización) IFS="\n"o IFS='\n'establecería IFS en la barra diagonal inversa de dos caracteres y n.

También puedes usar:

IFS='
'

o

IFS="
"

o

IFS=$'
'

Para pasar un fin de linea, aunque eso es menos legible (y uno no puede ver con excepción de usar cosas como set listen visi $IFScontiene otros caracteres de espaciado en ese código).

IFS=:, IFS=':', IFS=":", IFS=$':'Todos IFS conjunto a :por lo que no importa lo que usted usa.

$'...'está soportado (con variaciones) por al menos: ksh93, zsh, bash, mksh, busybox sh, FreeBSD sh. ksh93y bashtambién tiene una $"..."forma de citas utilizadas para la localización de texto, aunque rara vez se usa, ya que es engorroso implementar y usar de manera portátil y confiable.

Los shells esy fishtambién pueden usarse \nfuera de las comillas para expandirse a la nueva línea.

Algunas herramientas como printf, algunas implementaciones de echoo awktambién pueden expandirlas \npor sí mismas. Por ejemplo, uno puede hacer:

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

a la salida del carácter de nueva línea, pero tenga en cuenta que:

IFS = $ (printf '\ n')

no funcionará porque la sustitución de comando ( $(...)) elimina todos los caracteres de nueva línea finales. Sin embargo, puedes usar:

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

Lo que funciona porque la salida de printftermina en un "carácter, no en una nueva línea.

Ahora, para completar, en el rcshell y derivados (como eso akanga), $'\n'es de hecho la expansión de esa \nvariable (una variable cuyo nombre es la secuencia de dos caracteres \y n). Esos proyectiles no tienen una limitación en lo que los personajes nombres de variables pueden contener y sólo tienen un tipo de comillas: '...'.

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

rctodas las variables también se exportan al entorno, pero al menos en la variante Unix de rc, para nombres de variables como \n, la versión de la variable de entorno experimenta una forma de codificación:

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

( 0x5csiendo el valor de byte de ASCII \; vea también cómo esa variable de matriz se codificó con un byte 0x1 como separador).

Stéphane Chazelas
fuente
1
+1para el nivel inhumano de conocimiento habitual
Steven Penny
10

Esta es una cita de ANSI-C :

Las palabras de la forma $'string'son tratadas especialmente. La palabra se expande a string, con los caracteres con barra invertida reemplazados según lo especificado por el estándar ANSI C.

Por $'\n'lo tanto, se reemplaza por una nueva línea.

Esto no está relacionado con la expansión de parámetros de shell , a pesar del uso de $.

Stephen Kitt
fuente
6

Cadenas como $'\n'han sido introducidas por ksh93y actualmente no son parte del estándar POSIX.

Permiten usar la mayoría de los escapes de C, por ejemplo, $'\u2345'y los escapes que también son compatibles echo.

Tenga en cuenta que si no le gusta (en el caso de ksh93 o bash) usar ese método de escape, aún puede usar:

IFS='
'

que es equivalente pero más difícil de leer.

Por cierto: esta extensión ya ha pasado el comité estándar POSIX, pero está programada para SUSv8 que se espera que aparezca no antes del año 2020 porque primero tenemos que trabajar en nuestro retraso detrás de la lista actual de errores.

astuto
fuente
Las $'...'expansiones difieren de la de echo. Son más parecidos a los del argumento de formato printf. Para echo, se requiere un 0 en \0123while for $'...'y printfformat, \0123sería \012una nueva línea seguida de un literal 3.
Stéphane Chazelas
1
Tenga en cuenta que la $'...'especificación aún se está discutiendo. Aún quedan varios problemas por resolver con la redacción propuesta actualmente.
Stéphane Chazelas
IIRC, fue cerrado pero ha sido reabierto. Debido al hecho de que todavía hay mucho tiempo antes de que sea efectivo, no veo un problema real con eso.
schily
1
Se cerró, planteé varias objeciones, se volvió a abrir, luego se modificó, todavía hay varios problemas (la mayoría de ellos relacionados con la \uxxxxexpansión) y no hay una resolución a la vista que se adapte a las implementaciones existentes. Por lo tanto, es posible que no llegue a la próxima versión POSIX. Tal vez podrían dejar la \uxxxxexpansión para el problema8, por lo que todavía podemos tener al menos $'\n'.
Stéphane Chazelas