bash – Sustitución de comandos: dividir en una nueva línea pero no en un espacio

Pregunta:

Sé que puedo resolver este problema de varias maneras, pero me pregunto si hay alguna manera de hacerlo usando solo los componentes integrados de bash y, de no ser así, cuál es la forma más eficiente de hacerlo.

Tengo un archivo con contenido como

AAA
B C DDD
FOO BAR

con lo cual solo me refiero a que tiene varias líneas y cada línea puede tener o no espacios. Quiero ejecutar un comando como

cmd AAA "B C DDD" "FOO BAR"

Si uso cmd $(< file) obtengo

cmd AAA B C DDD FOO BAR

y si uso cmd "$(< file)" obtengo

cmd "AAA B C DDD FOO BAR"

¿Cómo consigo que cada línea se trate exactamente con un parámetro?

Respuesta:

Portablemente:

set -f              # turn off globbing
IFS='
'                   # split at newlines only
cmd $(cat <file)
unset IFS
set +f

O usando una subcapa para hacer que el IFS y los cambios de opción sean locales:

( 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 comando o variable que no está entre comillas dobles. Por lo tanto, debe desactivar la generación de nombres de archivo con set -f y configurar la división de campos con IFS para que solo las líneas nuevas se separen de los campos.

No hay mucho que ganar con las construcciones bash o ksh. Puede hacer que IFS local para una función, pero no set -f .

En bash o ksh93, puede almacenar los campos en una matriz, si necesita pasarlos a varios comandos. Necesita controlar la expansión en el momento de construir la matriz. Luego, "${a[@]}" expande a los elementos de la matriz, uno por palabra.

set -f; IFS=$'\n'
a=($(cat <file))
set +f; unset IFS
cmd "${a[@]}"

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top

web tasarım