以“反向顺序”应用括号扩展


21

例如{a..c}{1..3}扩展为a1 a2 a3 b1 b2 b3 c1 c2 c3

如果我想打印a1 b1 c1 a2 b2 c2 a3 b3 c3,是否有类似的方法可以做到?最简单的方法是什么?

Answers:


30

您可以这样做:

$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3

然后告诉外壳评估:

echo {a..c}1 {a..c}2 {a..c}3

10

对于这种特殊情况,我认为StéphaneChazelas提供的选择是最好的选择。

另一方面,当您扩展更复杂的内容时,此选项无法很好地扩展。因此,您可以使用以下方法实现相同的目的:

$ printf '%s\0' {a..c}{1..3} | sort -zk 1.2,1.2 | tr '\0' ' '

返回:

a1 b1 c1 a2 b2 c2 a3 b3 c3

似乎有些混乱,但是现在,我在命令中有了一个很大的控制权,只是在上面的命令中更改了两个字符;例如:

$ echo {a..b}{1..2}{a..b}{1..2}

这将扩展为:

a1a1 a1a2 a1b1 a1b2 a2a1 a2a2 a2b1 a2b2 b1a1 b1a2 b1b1 b1b2 b2a1 b2a2 b2b1 b2b2

假设我要1在第二个扩展中全部使用,然后是2

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.2,1.2 | tr '\0' ' '
a1a1 a1a2 a1b1 a1b2 b1a1 b1a2 b1b1 b1b2 a2a1 a2a2 a2b1 a2b2 b2a1 b2a2 b2b1 b2b2

假设我要a在第三个扩展中添加所有内容,然后是b

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.3,1.3 | tr '\0' ' '
a1a1 a1a2 a2a1 a2a2 b1a1 b1a2 b2a1 b2a2 a1b1 a1b2 a2b1 a2b2 b1b1 b1b2 b2b1 b2b2

假设我要1在第四个扩展中添加所有内容,然后是2

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.4,1.4 | tr '\0' ' '
a1a1 a1b1 a2a1 a2b1 b1a1 b1b1 b2a1 b2b1 a1a2 a1b2 a2a2 a2b2 b1a2 b1b2 b2a2 b2b2

假设我要在所有1a中间1b,然后是2a,然后是2b

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.2,1.3 | tr '\0' ' '
a1a1 a1a2 b1a1 b1a2 a1b1 a1b2 b1b1 b1b2 a2a1 a2a2 b2a1 b2a2 a2b1 a2b2 b2b1 b2b2

您甚至可以轻松地颠倒上述扩展中的任何顺序,只需r在前面的命令中添加一个即可。例如,最后一个:

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -rzk 1.2,1.3 | tr '\0' ' '
b2b2 b2b1 a2b2 a2b1 b2a2 b2a1 a2a2 a2a1 b1b2 b1b1 a1b2 a1b1 b1a2 b1a1 a1a2 a1a1

注意_1:通常,如果此最终扩展将用作参数列表,则尾随空格不是问题;但是,如果要删除它,可以将其添加到上述任何命令中,例如| sed 's/ $//'甚至| sed 's/ $/\n/'改变尾随空间newline

注意_2:在上面的示例中,为简单起见,我使用了两个元素的子集(即 {a,b} {1,2}):您可以使用任何有限长度的子集,而相应的命令,将是可比的。


5

bash,ksh,zsh

一个可以在(bash,ksh,zsh)中工作的衬板(并非所有shell都可以按相反的顺序进行“括号扩展”):

$ echo {3..1}{c..a} | rev
a1 b1 c1 a2 b2 c2 a3 b3 c3

可以使用的替代方法eval(仍然适用于bash,ksh,zsh,并且可能更含糊)是:

$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3

要了解会发生什么,请替换evalecho

$ echo echo '{a..c}'{1..3}
echo {a..c}1 {a..c}2 {a..c}3

(在eval扩展之后)执行的命令实际上是echo {a..c}1 {a..c}2 {a..c}3。它会根据您的需要扩展。

所有贝壳

有几个没有“括号扩展”的shell,因此,不可能将其用于“所有shell”。我们需要一个循环(尾随空白):

$ for i in 1 2 3; do for j in a b c; do printf "%s%s " "$j" "$i"; done; done; echo
a1 b1 c1 a2 b2 c2 a3 b3 c3 

如果您必须没有添加尾随空间:

s=""
for i in 1 2 3; do
    for j in a b c; do
        printf "%s%s%s" "$s" "$j" "$i"
        s=" "
    done
done
echo

版画

a1 b1 c1 a2 b2 c2 a3 b3 c3

如果您需要对许多值执行此操作,则需要使用与括号扩展类似的方法来生成数字列表$(seq 10)。并且,由于seq无法生成字母列表,因此我们需要将生成的数字转换为ascii:

s=""
for i in $(seq 4); do
    for j in $(seq 5); do
        printf "%s\\$(printf %03o $((96+j)))%s" "$s" "$i"
        s=" "
    done
done
echo

印刷品:

a1 b1 c1 d1 e1 a2 b2 c2 d2 e2 a3 b3 c3 d3 e3 a4 b4 c4 d4 e4

您也可以添加yash -o braceexpand到列表中。
斯特凡·查泽拉斯

@StéphaneChazelas我不确定是否应该。该命令在linux中yash -o braceexpand -c 'echo {3..1}{c..a}'打印3{c..a} 2{c..a} 1{c..a}。没有完全的“扩张”。
以撒

3
{a..c}1 {a..c}2 {a..c}3

括号中{a..c}{1..3}的扩展从左到右扩展,因此您首先得到a{1..3} b{1..3} c{1..3},然后将字母与数字组合成a1 a2 a3 b1 b2 b3 c1 c2 c3。要获得所需的订单,您将不得不使用上面稍长的表达式。


如果您想对大范围的“数字”执行此操作,那么它将不再可行。
RUBENGONÇALOMOROUÇO

3
@RUBENGONÇALOMOROUÇO不,如果您要处理大量数字,我建议您使用其他方法,例如双循环。这将适用于成千上万种组合,而在某些情况下,大括号可扩展我的触发器“参数列表过长”。
库萨兰达

2

使用循环:

for n in {1..3}; do printf '%s\n' {a..c}"$n"; done

这将循环您的第一个扩展,然后再扩展第二个字符。

如果只需要一行输出,则可以删除\n

for n in {1..3}; do printf '%s ' {a..c}"$n"; done

这不会给您尾随换行符,但是如果您将其传递给命令或变量,那应该不成问题。


1
为什么要这么多的否决权来解决循环问题?
艾萨克

h我一定看错了这个问题。更新
Jesse_b


0

一种简单的方法是使用排序(1.2、1.2表示您在第二个位置采用一个字符并在同一位置结束)。

$ for i in {a..c}{1..3}; do echo $i; done|sort -n -k1.2,1.2
a1
b1
c1
a2
b2
c2
a3
b3
c3

如果您希望将它们放在一行中,则可以这样使用tr:

$ for i in {a..c}{1..3}; do echo $i; done|sort -n -k1.2,1.2|tr '\n' ' '
a1 b1 c1 a2 b2 c2 a3 b3 c3

-2

通过以下方法完成

for i in {1..10}; do for j in {a..c}; do echo $j$i; done; done| perl -pne "s/\n/ /g"

输出

a1 b1 c1 a2 b2 c2 a3 b3 c3 a4 b4 c4 a5 b5 c5 a6 b6 c6 a7 b7 c7 a8 b8 c8 a9 b9 c9 a10 b10 c10

还考虑for i in {1..10}; do for j in {a..c}; do printf '%s ' "$j$i"; done; done;echo
Jeff Schaller
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.