たとえば、に{a..c}{1..3}
展開されa1 a2 a3 b1 b2 b3 c1 c2 c3
ます。
印刷したい場合、それa1 b1 c1 a2 b2 c2 a3 b3 c3
を行うための類似の方法はありますか?最も簡単な方法は何ですか?
たとえば、に{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
私1
が2番目の展開のすべてを望んでいると仮定し、次に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
3番目の拡張のすべてが必要だとし、次に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
は4番目の拡張のすべてを望んでいると仮定し、次に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:上記の例では、概念実証の単純化のために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
yash -o braceexpand -c 'echo {3..1}{c..a}'
印刷さ3{c..a} 2{c..a} 1{c..a}
れます。完全な「ブレース拡張」ではありません。
{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'
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
以下の方法で完了
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
yash -o braceexpand
リストに追加することもできます。