CcVHKakalLLOOPPOkKkkKk Asked: 2019-06-20 13:12:16 +0800 CST2019-06-20 13:12:16 +0800 CST 2019-06-20 13:12:16 +0800 CST 以“相反的顺序”应用大括号扩展 772 例如{a..c}{1..3}扩展为a1 a2 a3 b1 b2 b3 c1 c2 c3. 如果我想打印a1 b1 c1 a2 b2 c2 a3 b3 c3,是否有类似的方法可以做到这一点?最简单的方法是什么? bash brace-expansion 8 个回答 Voted Best Answer Stéphane Chazelas 2019-06-20T13:19:59+08:002019-06-20T13:19:59+08:00 你可以这样做: $ 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 alsjflalasjf.dev 2019-06-20T16:31:01+08:002019-06-20T16:31:01+08:00 对于这种特殊情况,我认为Stéphane Chazelas给出的选项是最好的。 另一方面,当您扩展更复杂的事物时,此选项无法很好地扩展。因此,您可以通过以下方式实现相同的目的: $ 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 Note_1 : 通常,如果这个最终扩展将被用作参数列表,尾随空格不是问题;但是如果你想摆脱它,你可以在上面的任何命令中添加,例如| sed 's/ $//';甚至| sed 's/ $/\n/',将尾随空格更改为newline 注意_2:在上面的示例中,我使用两个元素的子集(即: {a,b}和{1,2})只是为了简化概念证明:您可以使用任何有限长度的子集,并且相应的命令,将是可比的。 user232326 2019-06-20T14:05:49+08:002019-06-20T14:05:49+08:00 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 要了解会发生什么,请替换eval为echo: $ 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. 根据需要/需要扩展。 所有贝壳 有几个没有“大括号扩展”的外壳,因此,不可能将其用于“所有外壳”。我们需要一个循环(带有尾随空格): $ 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 Kusalananda 2019-06-20T13:19:30+08:002019-06-20T13:19:30+08:00 {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. 要获得您想要的订单,您必须使用上面稍长的表达式。 jesse_b 2019-06-20T13:21:09+08:002019-06-20T13:21:09+08:00 使用循环: 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 这不会给你一个尾随换行符,但如果你将它传递给一个不应该成为问题的命令或变量。 Dennis Williamson 2019-06-23T05:36:43+08:002019-06-23T05:36:43+08:00 这适用于您的简单案例并且可以扩展,但它很快就会失控。这不适用的更复杂的情况很容易构建。 反转大括号展开的顺序,然后交换字符: echo {1..3}{a..c} | sed -E 's/(.)(.)( ?)/\2\1\3/g' Hopping Bunny 2019-06-26T18:03:30+08:002019-06-26T18:03:30+08:00 一种简单的方法是使用排序(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 Praveen Kumar BS 2019-06-21T08:44:56+08:002019-06-21T08:44:56+08:00 通过以下方法完成 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
你可以这样做:
然后告诉外壳评估:
对于这种特殊情况,我认为Stéphane Chazelas给出的选项是最好的。
另一方面,当您扩展更复杂的事物时,此选项无法很好地扩展。因此,您可以通过以下方式实现相同的目的:
返回:
看起来有点乱,但现在,我对命令有很大的控制权,只需在上面的命令中更改两个字符;例如:
这将扩展为:
假设我想要
1
第二个扩展中的所有内容,那么2
:假设我想要
a
第三个扩展中的所有内容,那么b
:假设我想要
1
第四次扩展中的所有内容,那么2
:假设我想要
1a
中间的所有,然后1b
,然后2a
,然后2b
:您甚至可以很容易地反转上述扩展中的任何顺序,只需
r
在前面的命令中添加一个即可;例如最后一个:Note_1 : 通常,如果这个最终扩展将被用作参数列表,尾随空格不是问题;但是如果你想摆脱它,你可以在上面的任何命令中添加,例如
| sed 's/ $//'
;甚至| sed 's/ $/\n/'
,将尾随空格更改为newline
注意_2:在上面的示例中,我使用两个元素的子集(即: {a,b}和{1,2})只是为了简化概念证明:您可以使用任何有限长度的子集,并且相应的命令,将是可比的。
bash、ksh、zsh
一种适用于 (bash, ksh, zsh) 的衬里(并非所有 shell 都可以以相反的顺序进行“大括号扩展”):
另一种使用方式
eval
(仍然适用于 bash、ksh、zsh 并且可能更神秘)是:要了解会发生什么,请替换
eval
为echo
:执行的命令(在 eval 扩展之后)实际上是
echo {a..c}1 {a..c}2 {a..c}3
. 根据需要/需要扩展。所有贝壳
有几个没有“大括号扩展”的外壳,因此,不可能将其用于“所有外壳”。我们需要一个循环(带有尾随空格):
如果您必须没有添加尾随空格:
印刷
如果您需要对许多值执行此操作,我们需要使用类似于大括号扩展的东西来生成数字列表
$(seq 10)
。而且,由于 seq 无法生成字母列表,我们需要将生成的数字转换为 ascii:印刷:
中的大括号扩展
{a..c}{1..3}
从左到右扩展,因此您首先得到a{1..3} b{1..3} c{1..3}
,然后将字母与数字组合成a1 a2 a3 b1 b2 b3 c1 c2 c3
. 要获得您想要的订单,您必须使用上面稍长的表达式。使用循环:
这将循环通过您的第一个扩展,然后用第二个扩展每个字符。
如果您需要在一行上全部输出,则可以删除
\n
:这不会给你一个尾随换行符,但如果你将它传递给一个不应该成为问题的命令或变量。
这适用于您的简单案例并且可以扩展,但它很快就会失控。这不适用的更复杂的情况很容易构建。
反转大括号展开的顺序,然后交换字符:
一种简单的方法是使用排序(1.2,1.2 表示您在第二个位置取一个字符并在同一位置结束)。
如果您希望它们在一行中,您可以像这样使用 tr:
通过以下方法完成
输出