Tengo un programa en C que lee los argumentos de la línea de comandos de argv. ¿Es posible hacer una canalización para redirigir el contenido de un archivo como argumentos de línea de comando a mi programa? Supongamos que tengo un archivo arguments.dat
con este contenido:
0 0.2 302 0
Y quiero que mi programa sea llamado con:
./myprogram 0 0.2 302 0
Intenté lo siguiente:
cat arguments.dat | ./myprogram
sin éxito.
Respuestas
5 para la respuesta № 1Con la mayoría de los shells, puede insertar el contenido de un archivo en una línea de comando con $(<filename)
:
./myprogram $(<arguments.dat)
Si su shell no lo admite, entonces una de las formas más antiguas funcionará:
./myprogram $(cat arguments.dat)
./myprogram `cat arguments.dat` # need this one with csh/tcsh
(Si conoce la diferencia entre los argumentos de la línea de comando y la entrada del archivo, ¿no? ¿Por qué esperaría incluir los argumentos de la línea de comando en un programa?)
11 para la respuesta № 2
xargs
es tu respuesta:
cat arguments.dat | xargs ./myprogram
O más fácil:
xargs -a arguments.dat ./myprogram
Consulte el manual para las muchas maneras de personalizar xargs
. Por ejemplo, puede leer línea por línea en lugar de por palabra, y puede usar los argumentos en reemplazos más complejos.
2 para la respuesta № 3
... es decir: las respuestas a continuación se aplican a los casos en que no sería aceptable para ./myprogram --first-argument "first value"
ser cambiado en silencio ./myprogram --first-argument; ./myprogram "first value"
.
Si tus argumentos son literales de una línea.
Es decir, si su entrada se ve como:
--first-argument
first value
--second-argument
second value
y te refieres a esto para correr:
./myprogram --first-argument "first value" --second-argument "second value"
... entonces deberías usar (con bash 4.0 o posterior):
readarray -t args <arguments.dat
./myprogram "${args[@]}"
... o (también para bash 3.x):
args=( )
while IFS= read -r arg; do
args+=( "$arg" )
done <arguments.dat
./myprogram "${args[@]}"
Si sus argumentos están provistos de citas o de escape para distinguirlos
Es decir, si su archivo contiene algo como (tenga en cuenta que las nuevas líneas y los espacios sin comillas se comportan de manera idéntica aquí):
--first-argument "first value"
--second-argument "second value"
... y te refieres a esto para correr:
./myprogram --first-argument "first value" --second-argument "second value"
... entonces deberías usar:
args=( )
while IFS= read -r -d "" arg; do
args+=( "$arg" )
done < <(xargs printf "%s " <arguments.dat)
Si controlas tu formato de argumento
Utilice valores delimitados por NUL. Es decir, crea el archivo como tal:
printf "%s " "argument one" "argument two" >arguments.dat
... y analizarlo de la siguiente manera:
args=( )
while IFS= read -r -d "" arg; do
args+=( "$arg" )
done <arguments.dat
./myprogram "${args[@]}"
Esto funcionará con todo posible valores de argumento, incluso aquellos con líneas nuevas literales, comillas literales, barras invertidas literales u otros caracteres no imprimibles. (NULs literales no son posibles en las líneas de comando de UNIX, ya que las líneas de comando están compuestas por cadenas terminadas en NUL; por lo tanto, NUL es el único carácter que es completamente seguro de usar para separar de manera inequívoca argumentos en una cadena).
Si se desea dividir argumentos entre invocaciones
Esta subsección es relevante si el resultado deseado.(cuando hay más argumentos en su archivo que los que se pueden pasar a una invocación de su programa) hay varias invocaciones distintas del programa, cada una de las cuales recibe un subconjunto de argumentos. Esta es una familia de casos donde xargs
Es la herramienta adecuada para el trabajo.
Si está en una plataforma GNU, es posible que desee ejecutar xargs -a arguments.dat
en lugar de redirigir stdin; sin embargo, esto no es compatible con BSD xargs (como en MacOS), por lo que no se demuestra aquí.
Si tus argumentos son literales de una línea.
Con GNU xargs (la mayoría de las plataformas Linux):
xargs -d $"n" ./myprogram <arguments.dat
Con BSD xargs (MacOS, FreeBSD / OpenBSD / etc):
xargs -0 ./myprogram < <(tr "n" " " <arguments.dat)
Si sus argumentos están provistos de citas o de escape para distinguirlos
xargs ./myprogram <arguments.dat
Si ha generado entradas delimitadas por NUL
xargs -0 ./myprogram <arguments.dat