たとえば、{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
この特定のケースでは、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})は、概念実証の単純化のためです。任意の有限長のサブセットを使用でき、対応するコマンドは同等です。
(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
_
何が起こるかを理解するには、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
_
{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
にします。希望する順序を取得するには、上記の少し長い式を使用する必要があります。
これは単純なケースで機能し、拡張できますが、すぐに手に負えなくなります。これが機能しないより複雑なケースは簡単に作成できます。
ブレース展開の順序を逆にしてから、文字を入れ替えます。
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
これは末尾の改行を与えませんが、コマンドまたは変数に渡す場合は問題になりません。
簡単な方法の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