4du*_*ies 2 bash interpolation range
我不乐意使用eval,但我尝试的其他所有内容都因{a..b}语法限制而失败.这就是我所拥有的,是的,我知道我可以将这两个循环结合起来,但eval已经足够丑陋了.
cores=""
suffixes=""
np=$(nproc --all)
eval 'for i in {1..'$np'} ; do cores="$cores $i"; done'
for i in $cores ; do
suffixes="$suffixes "$(printf %02i $i)
done
Run Code Online (Sandbox Code Playgroud)
首先,一个积极的现代解决方案:
#!/bin/bash
# ^^^^- "printf -v" and C-style for loops both require bash, not /bin/sh
np=$(nproc --all)
cores=( )
for ((i=0; i<np; i++)); do
printf -v suffix '%02i' "$i"
cores[$i]=$suffix
done
Run Code Online (Sandbox Code Playgroud)
这会生成一个索引数组:其键是核心数,其值是后缀字符串.因此,您可以迭代"${!cores[@]}"以获取核心数列表; 在"${cores[@]}"获得后缀字符串列表,或使用"${cores[$i]}"查找后缀为核心$i.
接下来,一个更接近原始代码的解决方案,为现代bash构建:
#!/bin/bash
# ^^^^- "printf -v" and C-style for loops both require bash, not /bin/sh
np=$(nproc --all)
cores=""; suffixes=""
for ((i=0; i<np; i++)); do
printf -v suffix '%02i' "$i"
cores+=" $i"
suffixes+=" $suffix"
done
Run Code Online (Sandbox Code Playgroud)
您还可以仅在数组中构建核心数字,并在一个步骤中计算后缀数字:
# read cores from string into an array to allow safe evaluation even with unknown IFS
IFS=' ' read -r -a cores_arr <<<"$cores"
# ...and expand the full array, repeating the format string for every element
printf -v suffixes '%02i ' "${cores_arr[@]}"
Run Code Online (Sandbox Code Playgroud)
值得注意的是:
迭代扩展数组,即.for i in $cores,通常是不好的做法 - 如果你的价值保证只是数字,它可以是安全的,但要注意副作用:
*在数据中有一个,你会发现自己在当前目录中迭代文件.array=( "item one" "item two" )存储两个项目,其名称中包含空格; 如果你尝试设置string=' "item one" "item two" ',你会得到"item一个单词,one"作为第二个单词,等等.因此,迭代数组元素 - 即使这意味着从字符串读取到数组 - 是非常优选的.
循环使用任意数量的项目最好使用C风格的for循环.
nproc.这意味着我们不依赖于非POSIX工具seq.printf -v suffix将printf直接执行的字符串格式化操作的结果写入名为的变量suffix.(旁白:ksh93没有printf -v,但识别内部使用printf $()并避免子shell惩罚).请参阅bash-hackers页面printf.fork()shell在使用mkfifo()生成FIFO以捕获其输出之后需要关闭shell的另一个副本;读取该输出; wait()输入子shell以退出等;因此,它们最好保持在紧密循环之外).相比之下,如果你需要与POSIX sh的兼容性,那么我们仍然有$(( ))但没有(( ))(+=除了数学上下文之外没有任何操作,根本没有C风格的for循环).这让我们:
#!/bin/sh
build_suffix() {
np=$1; i=0
while [ "$i" -lt "$np" ]; do
printf '%02i ' "$i"
i=$((i+1))
done
}
suffixes=$(build_suffix "$(nproc --all)")
Run Code Online (Sandbox Code Playgroud)
...通过将整个循环放在单个子壳内,无论我们循环多少次,它都能给出一个恰好两个子壳的答案.