web-dev-qa-db-ja.com

ブレース拡張を「逆の順序」で適用します

たとえば、{a..c}{1..3}a1 a2 a3 b1 b2 b3 c1 c2 c3に展開されます。

a1 b1 c1 a2 b2 c2 a3 b3 c3を印刷したい場合は、類似の方法で印刷できますか?最も簡単な方法は何ですか?

あなたはできる:

$ 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
30

この特定のケースでは、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

少し乱雑に見えますが、今では、上記のコマンドで2つの文字を変更するだけで、順序に大きな制御があります。例えば:

$ 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

2番目の展開ですべての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

3番目の展開ですべての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

4番目の展開ですべての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

Note_2:上記の例では、2つの要素のサブセットを使用しています(つまり、{a、b}{1,2})は、概念実証の単純化のためです。任意の有限長のサブセットを使用でき、対応するコマンドは同等です。

10
matsib.dev

bash、ksh、zsh

(bash、ksh、zsh)で機能する1つのライナー(すべてのシェルが「ブレース展開」を逆の順序で実行できるわけではありません):

_$ 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_です。これは、必要に応じて拡張されます。

すべてのシェル

「ブレース展開」のないシェルがいくつかあるため、「すべてのシェル」には使用できません。ループが必要です(末尾に空白がある):

_$ 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
_
5
Isaac
{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にします。希望する順序を取得するには、上記の少し長い式を使用する必要があります。

3
Kusalananda

これは単純なケースで機能し、拡張できますが、すぐに手に負えなくなります。これが機能しないより複雑なケースは簡単に作成できます。

ブレース展開の順序を逆にしてから、文字を入れ替えます。

echo {1..3}{a..c} | sed -E 's/(.)(.)( ?)/\2\1\3/g'

ループを使用する:

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

これは最初の展開をループし、次に2番目の展開で各キャラクターを展開します。

すべてを1行で出力する必要がある場合は、\n

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

これは末尾の改行を与えませんが、コマンドまたは変数に渡す場合は問題になりません。

2
jesse_b

簡単な方法の1つは、sortを使用することです(1.2、1.2は、2番目の位置で1つの文字を受け取り、同じ場所で終了することを意味します)。

$ 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

それらを1行にしたい場合は、次のように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
0
Hopping Bunny