我想生成这样的文件([1-3]X[1-5]
的笛卡尔积):
1 1
1 2
1 3
1 4
1 5
2 1
2 2
2 3
2 4
2 5
3 1
3 2
3 3
3 4
3 5
我可以使用嵌套循环来完成这个操作,如下所示:
for i in $(seq 3)
do
for j in $(seq 5)
do
echo $i $j
done
done
有没有不用循环的解决方案?
合并两个花括号展开!
$ printf "%s\n" {1..3}" "{1..5}
1 1
1 2
1 3
1 4
1 5
2 1
2 2
2 3
2 4
2 5
3 1
3 2
3 3
3 4
3 5
这可以通过使用单个花括号扩展来实现:
$ echo {1..5}
1 2 3 4 5
然后与另一个合并:
$ echo {1..5}+{a,b,c}
1+a 1+b 1+c 2+a 2+b 2+c 3+a 3+b 3+c 4+a 4+b 4+c 5+a 5+b 5+c
join -j 999999 -o 1.1,2.1 file1 file2
由于字段 999999 很可能不存在,因此对于两个集合来说被认为是相等的,因此 join
必须执行笛卡尔积。它使用 O(N+M) 内存,在我的机器上产生 100..200 Mb/sec 的输出。
我不喜欢使用 "shell brace expansion" 方法,例如 echo {1..100}x{1..100}
,因为它使用 O(N*M) 内存,并且在使用不当时可能会使您的机器崩溃。这很难停止,因为 ctrl+c 不会中断由 shell 自身执行的大括号展开。
$ echo -en {a..c}"\tx\n" | sed 's/^/1\t/' > a.txt
$ cat a.txt
1 a x
1 b x
1 c x
$ echo -en "foo\nbar\n" | sed 's/^/1\t/' > b.txt
$ cat b.txt
1 foo
1 bar
请注意,sed
命令用于添加每行的标识符。这个标识符必须对于所有行以及所有文件都是相同的,这样 join
命令才能给你一个笛卡尔积,而不是放弃一些结果行。因此,join
的使用方法如下:
$ join -j 1 -t $'\t' a.txt b.txt | cut -d $'\t' -f 2-
a x foo
a x bar
b x foo
b x bar
c x foo
c x bar
在合并这两个文件之后,使用 cut
命令作为替代方法来删除前面加上的“1”列。
{1..3}
与seq 3
或seq 1 3
相同,只是它是Shell自带的。 - fedorquiecho {1..3}" "{1..5} | xargs -n 2
。 - fedorquiecho {1..2}{3..4}
会产生完整的交叉乘积13 14 23 24
,而不是1 23 24
或13 23 4
? - Jonahprintf "%s\n" {a,e,z}" "{x,9,u}
。 - AKX