6

我今天注意到 Bashprintf有一个-v选项

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

如果我这样调用它会起作用

$ printf -v var "Hello world"

$ printf "$var"
Hello world

来自管道它不起作用

$ 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'
4

3 回答 3

9

xargs将调用/usr/bin/printf(或系统上安装该二进制文件的任何位置)。它不会调用 bash 的内置函数。并且只有内置的(或采购脚本或类似的)可以修改 shell 的环境。

即使它可以调用 bash 的内置xargs函数,您的示例中的 the 也会在转售中运行。subshel​​l 无论如何都不能修改它的父环境。所以你正在尝试的东西是行不通的。

如果我正确理解您的示例,我会看到一些选项;样本数据:

$ cat input
abc other stuff
def ignored
cba more stuff

简单变量(有点棘手,具体取决于您想要什么):

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

如果您想要数组中的单个单词,则使用数组:

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

或者,如果您想要每个数组元素中的整行:

$ IFS=$'\n' var=($(grep a input)) ; unset IFS
$ echo "${var[0]}"-"${var[1]}"
abc other stuff-cba more stuff
于 2012-06-12T20:10:16.753 回答
1

有两个 printf——一个是 shell bultin,如果你只运行 printf 就会调用它,另一个是常规二进制文件,通常是 /usr/bin/printf。后者不带 -v 参数,因此出现错误消息。由于printfxargs此处的参数,因此运行的是二进制文件,而不是 shell bulitin。此外,由于它位于管道的接收端,因此它作为子进程运行。变量只能从父进程继承到子进程,但不能相反,因此即使 printf 二进制文件可以修改环境,父进程也不会看到更改。因此,您的命令无法正常工作有两个原因。但你总是可以做到var=$(something | bash -c 'some operation using builtin printf')的。

于 2012-06-12T20:10:52.307 回答
0

Mat 对发生的事情和原因给出了很好的解释。

如果您想遍历命令的输出并使用 Bash 的sprintf-styleprintf功能 ( -v) 将变量设置为连续值,您可以这样做:

grep "Hello world" test.txt | xargs bash -c 'printf -v var "%-25s" "$@"; do_something_with_formatted "$var"' _ {} \;
于 2012-06-12T21:38:40.273 回答