我不乐意使用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
答案 0 :(得分:7)
首先,一个积极的现代解决方案:
#!/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
这将生成一个索引数组:其键是核心数,其值是后缀字符串。因此,您可以迭代"${!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
您也可以只在数组中构建核心数字,并在一步中计算后缀数字:
# 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[@]}"
值得注意的是:
迭代扩展数组,即。 for i in $cores
,通常是不好的做法 - 如果您的值保证只是数字,那么它可以是安全的,但要注意副作用:
*
,您会发现自己正在迭代当前目录中的文件。array=( "item one" "item two" )
存储两个项目,两个名字都有空格;如果您尝试设置string=' "item one" "item two" '
,则会将"item
作为一个单词,one"
作为第二个单词,等等。因此,迭代数组元素 - 即使这意味着从字符串读取到数组 - 是强烈首选。
最好使用C-style for
loop对任意数量的项目进行循环。
nproc
之外没有外部命令。这意味着我们不依赖于诸如seq
之类的非POSIX工具。printf -v suffix
将printf
执行的字符串格式化操作的结果直接写入名为suffix
的变量。 (旁白:ksh93没有printf -v
,但承认在$()
内使用printf并避免了子shell惩罚)。见the bash-hackers page on printf
。fork()
生成FIFO以捕获其输出之后,每个子shell都需要mkfifo()
另一个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)")
...通过将整个循环放在单个子shell中,无论我们循环多少次,都可以给出一个恰好两个子shell的答案。
答案 1 :(得分:1)
suffixes=''
np="$(nproc --all)"
for ((i=0; i <$np; ++i)); do suffixes="$suffixes $(printf %02i $i)"; done
答案 2 :(得分:0)
感谢大家的投入。它给了我一些值得思考的东西。我已经决定更换for循环并调用printf(1):
np=$(nproc --all)
suffixes=$(eval "echo {01..$np}")
它简洁明了,引用很明显。我还没有对eval感到兴奋,但是它没有使用不受信任的数据,它在我正在做的整体方案中贡献了非常(非常!)的小运行时间。