printf, ignorando el exceso de argumentos?

Me di cuenta hoy Bash printf tiene un -v opción

-v var    assign the output to shell variable VAR rather than
          display it on the standard output

Si invoco así funciona

$ printf -v var "Hello world"

$ printf "$var"
Hello world

Viniendo de una tubería no funciona

$ grep "Hello world" test.txt | xargs printf -v var
-vprintf: warning: ignoring excess arguments, starting with `var'

$ grep "Hello world" test.txt | xargs printf -v var "%s"
-vprintf: warning: ignoring excess arguments, starting with `var'

preguntado el 12 de junio de 12 a las 21:06

3 Respuestas

xargs invocará /usr/bin/printf (o donde sea que ese binario esté instalado en su sistema). No invocará la función incorporada de bash. Y solo una función integrada (o la obtención de un script o similar) puede modificar el entorno del shell.

Incluso si pudiera llamar al incorporado de bash, el xargs en su ejemplo se ejecuta en una subventa. El subshell no puede modificar el entorno de su padre de todos modos. Así que lo que estás intentando no puede funcionar.

Algunas opciones que veo si entiendo su muestra correctamente; Data de muestra:

$ cat input
abc other stuff
def ignored
cba more stuff

Variable simple (un poco complicado dependiendo de lo que quieras exactamente):

$ var=$(grep a input)
$ echo $var
abc other stuff cba more stuff
$ echo "$var"
abc other stuff
cba more stuff

Con una matriz si desea palabras individuales en las matrices:

$ var=($(grep a input))
$ echo "${var[0]}"-"${var[1]}"
abc-other

O si desea las líneas completas en cada elemento de la matriz:

$ IFS=$'\n' var=($(grep a input)) ; unset IFS
$ echo "${var[0]}"-"${var[1]}"
abc other stuff-cba more stuff

Respondido el 12 de junio de 12 a las 21:06

Hay dos printf: uno es un bultin de shell y se invoca si solo ejecuta printf y el otro es un binario normal, generalmente /usr/bin/printf. Este último no toma un argumento -v, de ahí el mensaje de error. Ya que printf es un argumento para xargs aquí, se ejecuta el binario, no el shell bulitin. Además, dado que se encuentra en el extremo receptor de una canalización, se ejecuta como un subproceso. Las variables solo se pueden heredar del proceso principal al secundario, pero no al revés, por lo que incluso si el binario printf pudiera modificar el entorno, el cambio no sería visible para el proceso principal. Entonces, hay dos razones por las que su comando no puede funcionar. Pero siempre puedes hacer var=$(something | bash -c 'some operation using builtin printf').

Respondido el 13 de junio de 12 a las 09:06

No es que esté al final de una tubería, es que es un argumento para xargs que solo acepta ejecutables externos (que es /usr/bin/printf). Además, su ejemplo no tiene ningún resultado a menos que elimine el -v. - dennis williamson

Mat da una excelente explicación de lo que está pasando y por qué.

Si desea iterar sobre la salida de un comando y establecer una variable en valores sucesivos usando Bash sprintf-Estilo printf característica (-v), puedes hacerlo así:

grep "Hello world" test.txt | xargs bash -c 'printf -v var "%-25s" "$@"; do_something_with_formatted "$var"' _ {} \;

Respondido el 12 de junio de 12 a las 22:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.