不可以。扩展的上下文与普通命令扩展上下文基本相同,其中所有扩展都会被处理并将生成的单词以不可变的方式保存以进行迭代。在for-in循环中没有惰性迭代器。当然,扩展可能具有副作用并与glob混合使用,因此必须急切地评估它们。这就是为什么在可能同时执行任务时,
find -exec [+;]
仍然比globstar经常推荐的原因。
我对这个4096问题无法发表任何意见。我认为这两者并不真正可比。Shell for..in只是扩展单词并对其进行迭代。
一个相关的常见问题是是否可以像预读取要分配的下一个值之类的操作。据我所知,没有任何类似bourne的shell可以访问单词列表。你必须使用数组。基本上,通过数组可以克服所有
for..in
的限制。
以下是我为Bash编写的有趣的懒洋洋的coproc生成器。它非常无用。
coproc x { while :; do find . -type f -maxdepth 1 -exec sh -c 'read; echo "$1"' -- {} \;; done; };
while :; do
echo 1 >&"${x[1]}"
read -ru "${x[0]}" file
echo "$file"
sleep 1
done
还有一个与问题无关的关于for..in
的小提示--在ksh93和Bash的git开发分支中,可以以有趣的方式利用“控制变量”。
function f {
nameref x
for x; do
x=hi
done
}
typeset -a arr
f 'arr['{0..3}']'
typeset -p arr
每次迭代都会将给定对象的引用分配给x。当然,在ksh中,这可以是任何复杂的数据类型。我想这可能被滥用以某种方式模拟懒惰。不幸的是,这种模式似乎在mksh中不起作用。
编辑忘记自从写这篇文章以来,我发现很多shell确实优化了for x
语法。我假设至少for x in
是写时复制的,并且仅在循环内部使用shift
或set
时才复制位置参数。