考虑这行代码,其中deps包含依赖项列表:
IFS=',' printf "setup-x86.exe -q -p='%s'\n" "${deps[*]}"
我将IFS
设置为,
,用于单次调用printf,但奇怪printf
似乎不尊重IFS
,因为它不会展开deps
以逗号分隔的列表。
另一方面,如果我像这样设置IFS:
IFS=','
printf "setup-x86.exe -q -p='%s'\n" "${deps[*]}"
printf正确地将deps扩展为以逗号分隔的列表。
我在这里想念一下吗?
答案 0 :(得分:6)
在此命令行中:
IFS=',' printf "setup-x86.exe -q -p='%s'\n" "${deps[*]}"
printf
不展开"${deps[*]}"
。 shell进行扩展。事实上,这总是如此。尽管printf
碰巧是shell内置的,但它对其参数没有做任何特殊处理,并且您将获得与外部printf
完全相同的行为。
语法
envvar=value program arg1 arg2 arg3
导致shell将envvar=value
添加到提供给program
的环境变量列表中,并将字符串arg1
,arg2
和arg3
添加到制作成program
的argv列表。在所有这些发生之前,shell会执行各种类型的正常扩展,这将导致value
中引用的shell变量和三个参数被替换为它们的值。但是环境变量设置envvar=value
不是shell执行环境的一部分。
同样地,
FOO=World echo "Hello, $FOO"
在FOO=World
的参数中展开$FOO
时,不会使用echo
。 "Hello, $FOO"
由shell的执行环境中的shell扩展,然后作为参数传递给echo
,FOO=World
作为其环境的一部分传递给echo
。 / p>
将变量设置放在单独的命令中是完全不同的。
IFS=','; printf "setup-x86.exe -q -p='%s'\n" "${deps[*]}"
在shell解析IFS
命令之前,首先在 shell的环境中设置printf
的值。当shell在参数中进行扩展时,它最终会传递给printf
,它使用IFS
的值来扩展数组deps[*]
。在这种情况下,IFS
不包含在传递给printf
的环境变量中,除非先前已导出IFS
。
使用内置IFS
read
的{{1}}可能会让人感到困惑,但它与上述内容完全一致。在命令
IFS=, read A B C
IFS=,
作为环境变量列表的一部分传递给read
。 read
消耗一行输入,并在其环境中查询IFS
的值,以便弄清楚如何将输入行拆分为单词。
为了在参数中进行参数扩展而更改IFS
,必须在shell的环境中进行更改,这是一个全局更改。由于您很少想要全局更改IFS
的值,因此常见的习惯用法是在使用()
创建的子shell中更改它:
( IFS=,; printf "setup-x86.exe -q -p='%s'\n" "${deps[*]}"; )
可能会做你想要的。
答案 1 :(得分:0)
你可以。只需保存它,使用它并重置它:
oldifs=$IFS
IFS=','
printf "setup-x86.exe -q -p='%s'\n" "${deps[*]}"
IFS=$oldifs
现在为您的命令,您可以通过在命令之间放置;
来在一行上执行此操作:
IFS=','; printf "setup-x86.exe -q -p='%s'\n" "${deps[*]}"
您仍然需要保存并恢复IFS
。
您可以将IFS
设置为一次性交易的唯一地方是while
循环。 E.g:
while IFS=$'\n' read line; do
....
done
在这种情况下,它只是在while循环中应用。