Sé que puedo resolver este problema de varias maneras, pero me pregunto si hay una manera de hacerlo usando solo bash incorporado y, de no ser así, cuál es la forma más eficiente de hacerlo.
Tengo un archivo con contenidos como
AAA
B C DDD
FOO BAR
con lo cual solo quiero decir que tiene varias líneas y cada línea puede o no tener espacios. Quiero ejecutar un comando como
cmd AAA "B C DDD" "FOO BAR"
Si uso cmd $(< file)
consigo
cmd AAA B C DDD FOO BAR
y si uso cmd "$(< file)"
consigo
cmd "AAA B C DDD FOO BAR"
¿Cómo hago para que cada línea sea tratada exactamente como un parámetro?
Respuesta aceptada:
Portabilidad:
set -f # turn off globbing
IFS='
' # split at newlines only
cmd $(cat <file)
unset IFS
set +f
O usando una subcapa para hacer el IFS
y la opción cambia local:
( set -f; IFS='
'; exec cmd $(cat <file) )
El shell realiza la división de campos y la generación de nombres de archivo en el resultado de una sustitución de variable o comando que no está entre comillas dobles. Por lo tanto, debe desactivar la generación de nombres de archivo con set -f
y configure la división de campos con IFS
para hacer que solo las líneas nuevas separen los campos.
No hay mucho que ganar con construcciones bash o ksh. Puedes hacer IFS
local a una función, pero no set -f
.
En bash o ksh93, puede almacenar los campos en una matriz, si necesita pasarlos a varios comandos. Debe controlar la expansión en el momento de construir la matriz. Entonces "${a[@]}"
se expande a los elementos de la matriz, uno por palabra.
set -f; IFS=$'n'
a=($(cat <file))
set +f; unset IFS
cmd "${a[@]}"