Estoy tratando de almacenar varias líneas en una variable bash, pero parece que no funciona.
Por ejemplo, si enumero /bin
un archivo por línea y lo almaceno $LS
, luego lo paso $LS
como stdin wc
, siempre devuelve 1:
$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1
Si intento imprimir en la pantalla, obtengo varios resultados: echo
imprime todas las líneas en una sola línea, mientras printf
imprime solo la primera línea:
#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS
Entonces, ¿una variable bash puede contener varias líneas?
printf "%s\n" $LS
lo harían.wc
y otros comandos:wc -l <<< "$LS"
printf '%s\n' "$LS"
si quieres ver nueva línea. Eso está mal escrito, lo arregló!Las nuevas líneas están en la variable.
LS=$(ls -1)
establece la variableLS
en la salida dels -1
(que produce la misma salida quels
, por cierto, excepto cuando la salida va a una terminal), menos las nuevas líneas finales.El problema es que está eliminando las nuevas líneas cuando imprime el valor. En un script de shell,
$LS
no significa "el valor de la variableLS
", significa "tomar el valor deLS
, dividirlo en palabras segúnIFS
e interpretar cada palabra como un patrón global". Para obtener el valor deLS
, necesita escribir"$LS"
, o más generalmente poner$LS
entre comillas dobles.echo "$LS"
imprime el valor deLS
, excepto en algunos shells que interpretan caracteres de barra invertida, y a excepción de algunos valores que comienzan con-
.printf "$LS"
imprime el valorLS
siempre que no contenga ningún carácter de porcentaje o barra invertida y (con la mayoría de las implementaciones) no comience con-
.Para imprimir el valor de
LS
exactamente, useprintf %s "$LS"
. Si quieres una nueva línea al final, úsalaprintf '%s\n' "$LS"
.Tenga en cuenta que
$(ls)
no es, en general, la lista de archivos en el directorio actual. Esto solo funciona cuando tienes nombres de archivo suficientemente mansos. Para obtener la lista de nombres de archivo (excepto archivos punto), es necesario utilizar un comodín:*
. El resultado es una lista de cadenas, no una cadena, por lo que no puede asignarla a una variable de cadena; puede usar una variable de matrizfiles=(*)
en shells que las admitan (ksh93, bash, zsh).Para obtener más información, consulte ¿Por qué mi script de shell se ahoga en espacios en blanco u otros caracteres especiales?
fuente
Lo antes mencionado
Es la única solución correcta.
Permítanme demostrar que las otras soluciones propuestas, tanto con
echo
yprintf
, simplemente no funcionan correctamente:(También se puede probar con
V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"
y variaciones).Mientras que
\n
en los nombres de archivo puede no ser tan común, almacenargit diff
en una variable, y sus posibilidades de encontrar literales\n
aumentan dramáticamente.fuente
ksh
yzsh
también soporteprint -r -- "$LS"
yzsh
también tieneecho -E - $LS
.csh
tieneecho $LS:q
sin embargo que no emitirá el carácter de nueva línea Si $ LS está vacía, y conseguir un valor de varias líneas en $ LS en el primer lugar es bastante complicado en CSH.