我今天注意到Bash printf
有一个-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'
答案 0 :(得分:8)
xargs
将调用/usr/bin/printf
(或在您的系统上安装二进制文件的任何位置)。它不会调用bash的内置函数。只有内置(或采购脚本或类似内容)才能修改shell的环境。
即使它可以调用bash的内置函数,您示例中的xargs
也会在子集中运行。无论如何,子shell无法修改它的父级环境。所以你正在尝试的东西是行不通的。
如果我理解你的样本,我会看到一些选项;样本数据:
$ 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
答案 1 :(得分:1)
有两个printf - 一个是shell bultin,如果你只运行printf而另一个是常规二进制文件,通常是/ usr / bin / printf,则调用它。后者不接受-v参数,因此出现错误消息。由于printf
是xargs
的参数,因此运行二进制文件,而不是shell bulitin。此外,由于它位于管道的接收端,因此它作为子进程运行。变量只能从父进程继承到子进程,而不是相反,因此即使printf二进制文件可以修改环境,父进程也不会看到更改。因此,有两个原因导致您的命令无法工作。但你总是可以做var=$(something | bash -c 'some operation using builtin printf')
。
答案 2 :(得分:0)
Mat给出了正在发生的事情及其原因的绝佳解释。
如果要迭代命令的输出并使用Bash的sprintf
- 样式printf
功能(-v
)将变量设置为连续值,则可以这样做:
grep "Hello world" test.txt | xargs bash -c 'printf -v var "%-25s" "$@"; do_something_with_formatted "$var"' _ {} \;