bash 中多个 `seq` 的外积
Outer product from multiple `seq`s in bash
来自3个序列(例如):
seq 0 0.2 1
,
seq 0 0.3 1.5
,
seq 0 0.5 1
我想生成类似的东西
0:0:0 0:0:0.5 0:0:1 0:0.3:0 0:0.3:0.5 0:0.3:1...
。它们采用 a:b:c
格式,其中 a 来自第一个序列,b 来自第二个序列,c 来自第三个序列,所有组合都出现一次。
如果这些是整数并且具有统一步长,我可以使用 {1..10}:{2..10}:{3..10}
,并且它工作得很好,但是无论如何可以将这个大括号函数扩展到非整数和非统一步长吗?
非常感谢!
老实说,对于这项工作,awk
是比 seq
更好的工具;它是 POSIX 标准化的,在 I/O 时比 bash 快得多,而且您可以 运行 只有一个实例来生成所有输出:
awk '
BEGIN {
for(a=0; a<=1; a+=0.2) {
for(b=0; b<=1.5; b+=0.2) {
for(c=0; c<=1; c+=0.5) {
printf("%.1f:%.1f:%.1f\n", a, b, c);
}
}
}
}' </dev/null
但是,如果出于某种原因您真的想要使用seq
,嵌套三个BashFAQ #1 while read
循环将完成这项工作:
#!/usr/bin/env bash
while read -r a; do
while read -r b; do
while read -r c; do
printf '%.1f:%.1f:%.1f\n' "$a" "$b" "$c"
done < <(seq 0 0.5 1)
done < <(seq 0 0.3 1.5)
done < <(seq 0 0.2 1)
在我的系统上,seq
版本 运行s 在 ~0.3 秒挂钟,而 awk
版本需要 ~0.01s。
这可能适合您(GNU sed 和并行):
parallel echo ::: $(seq 0 0.2 1) ::: $(seq 0 0.3 1.5) ::: $(seq 0 0.5 1) |
sed -z 'y/ \n/: /;s/\.0//g'
另一种方法,使用 bash 和 sed:
echo {00..10..2}:{00..15..3}:{00..10..5} | sed 's/\B/./g;s/\.0//g'
来自3个序列(例如):
seq 0 0.2 1
,
seq 0 0.3 1.5
,
seq 0 0.5 1
我想生成类似的东西
0:0:0 0:0:0.5 0:0:1 0:0.3:0 0:0.3:0.5 0:0.3:1...
。它们采用 a:b:c
格式,其中 a 来自第一个序列,b 来自第二个序列,c 来自第三个序列,所有组合都出现一次。
如果这些是整数并且具有统一步长,我可以使用 {1..10}:{2..10}:{3..10}
,并且它工作得很好,但是无论如何可以将这个大括号函数扩展到非整数和非统一步长吗?
非常感谢!
老实说,对于这项工作,awk
是比 seq
更好的工具;它是 POSIX 标准化的,在 I/O 时比 bash 快得多,而且您可以 运行 只有一个实例来生成所有输出:
awk '
BEGIN {
for(a=0; a<=1; a+=0.2) {
for(b=0; b<=1.5; b+=0.2) {
for(c=0; c<=1; c+=0.5) {
printf("%.1f:%.1f:%.1f\n", a, b, c);
}
}
}
}' </dev/null
但是,如果出于某种原因您真的想要使用seq
,嵌套三个BashFAQ #1 while read
循环将完成这项工作:
#!/usr/bin/env bash
while read -r a; do
while read -r b; do
while read -r c; do
printf '%.1f:%.1f:%.1f\n' "$a" "$b" "$c"
done < <(seq 0 0.5 1)
done < <(seq 0 0.3 1.5)
done < <(seq 0 0.2 1)
在我的系统上,seq
版本 运行s 在 ~0.3 秒挂钟,而 awk
版本需要 ~0.01s。
这可能适合您(GNU sed 和并行):
parallel echo ::: $(seq 0 0.2 1) ::: $(seq 0 0.3 1.5) ::: $(seq 0 0.5 1) |
sed -z 'y/ \n/: /;s/\.0//g'
另一种方法,使用 bash 和 sed:
echo {00..10..2}:{00..15..3}:{00..10..5} | sed 's/\B/./g;s/\.0//g'