Örneğin, {a..c}{1..3}
genişler a1 a2 a3 b1 b2 b3 c1 c2 c3
.
Basmak istesem a1 b1 c1 a2 b2 c2 a3 b3 c3
, bunu yapmanın benzer bir yolu var mı? En basit yol nedir?
Örneğin, {a..c}{1..3}
genişler a1 a2 a3 b1 b2 b3 c1 c2 c3
.
Basmak istesem a1 b1 c1 a2 b2 c2 a3 b3 c3
, bunu yapmanın benzer bir yolu var mı? En basit yol nedir?
Yanıtlar:
Yapabilirsin:
$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3
Hangi kabuktan değerlendirmek için söyler:
echo {a..c}1 {a..c}2 {a..c}3
Bu özel durum için, Stéphane Chazelas'ın verdiği seçeneğin en iyisi olduğunu düşünüyorum .
Öte yandan, daha karmaşık şeyleri genişlettiğinizde, bu seçenek iyi ölçeklenemez. Böylece, bununla aynı şeyi başarabilirsiniz:
$ printf '%s\0' {a..c}{1..3} | sort -zk 1.2,1.2 | tr '\0' ' '
hangi döner:
a1 b1 c1 a2 b2 c2 a3 b3 c3
Biraz dağınık görünüyor, ama şimdi, sıradaki büyük kontrolüm var, sadece yukarıdaki komuttaki iki karakteri değiştiriyorum; Örneğin:
$ echo {a..b}{1..2}{a..b}{1..2}
bu, aşağıdakilere genişleyecektir:
a1a1 a1a2 a1b1 a1b2 a2a1 a2a2 a2b1 a2b2 b1a1 b1a2 b1b1 b1b2 b2a1 b2a2 b2b1 b2b2
Sanırım hepsini 1
ikinci genişlemede istiyorum, sonra 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
Diyelim ki a
üçüncü genişlemede hepsini istiyorum , sonra 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
Dördüncü genişlemede hepsini istiyorum , sonra 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
Diyelim ki hepsini 1a
ortada istiyorum , sonra 1b
, sonra 2a
, sonra 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
Yukarıdaki açılımlardaki herhangi bir sırayı, kolayca r
önceki komutunuza ekleyerek kolayca geri alabilirsiniz ; örneğin, sonuncusu:
$ 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
Not_1 : genellikle, bu son genişleme bir argüman listesi olarak kullanılacaksa, sondaki boşluk sorun olmaz; ama ondan kurtulmak istiyorsan, yukarıdaki komutlardan herhangi birine ekleyebilirsin, örneğin| sed 's/ $//'
; hatta| sed 's/ $/\n/'
, bu sondaki alanı değiştirmeknewline
Not_2 : Yukarıdaki örneklerde, kavramın ispatındaki basitlik içiniki öğenin alt kümelerini kullanıyorum (yani: {a, b} ve {1,2} ): Herhangi bir sonlu uzunlukta alt kümeleri kullanabilirsiniz karşılık gelen komut, karşılaştırılabilir olurdu.
İçinde çalışan bir astar (bash, ksh, zsh) (tüm kabukları ters sırayla "Destek genişletme" yapamaz):
$ echo {3..1}{c..a} | rev
a1 b1 c1 a2 b2 c2 a3 b3 c3
eval
(Hala bash, ksh, zsh ve daha şifreli olabilir) kullanımına alternatif :
$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3
Yerine ne olacağını anlamak için eval
birlikte echo
:
$ echo echo '{a..c}'{1..3}
echo {a..c}1 {a..c}2 {a..c}3
Yürütülen komut (eval genişlemesinden sonra) aslında echo {a..c}1 {a..c}2 {a..c}3
. İstediğiniz / ihtiyaç duyduğunuz kadar genişler.
"Ayraç genişlemesi" olmayan birkaç mermi vardır, bu yüzden "tüm mermiler" için kullanmak mümkün değildir. Bir döngüye ihtiyacımız var (takip eden beyaz boşlukla):
$ 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
Eklenen bir boşluk bırakmamış olmanız gerekiyorsa:
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
Baskılar
a1 b1 c1 a2 b2 c2 a3 b3 c3
Bunu birçok değer için yapmanız gerekiyorsa, bir sayı listesi oluşturmak için ayraç genişletmesine benzer bir şey kullanmamız gerekir $(seq 10)
. Sıra, bir harf listesi oluşturamadığından, üretilen sayıları ascii'ye dönüştürmemiz gerekir:
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
baskılar:
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}'
basılıyor 3{c..a} 2{c..a} 1{c..a}
. Tam bir "ayraç genişletme" değil.
{a..c}1 {a..c}2 {a..c}3
Parantez açılımları {a..c}{1..3}
soldan sağa doğru genişler, böylece önce siz alırsınız a{1..3} b{1..3} c{1..3}
, sonra harfler sayılarla birleştirilir a1 a2 a3 b1 b2 b3 c1 c2 c3
. İstediğiniz sırayı almak için yukarıdaki biraz daha uzun ifadeyi kullanmanız gerekir.
Bir döngü kullanarak:
for n in {1..3}; do printf '%s\n' {a..c}"$n"; done
Bu, ilk genişletme işleminizi gerçekleştirecek ve ardından her karakteri ikinci ile genişletecektir.
Çıktıya tek bir satırda ihtiyacınız varsa, şunları kaldırabilirsiniz \n
:
for n in {1..3}; do printf '%s ' {a..c}"$n"; done
Bu size sonda bir yeni hat vermeyecek, ancak eğer bir sorun olmamalı bir komuta veya değişkene geçiyorsanız.
Bu, basit durum için işe yarar ve uzatılabilir, ancak hızlı bir şekilde elden çıkar. Bunun işe yaramayacağı daha karmaşık durumlarda yapılması kolaydır.
Ayraç genişlemelerinin sırasını ters çevirin, ardından karakterleri değiştirin:
echo {1..3}{a..c} | sed -E 's/(.)(.)( ?)/\2\1\3/g'
Basit bir yöntem, sıralama kullanmak olacaktır (1.2,1.2, ikinci bir karakterden birini aldığınız ve aynı yerde bittiğiniz anlamına gelir).
$ 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
Onları bir satırda istiyorsanız, tr gibi kullanabilirsiniz:
$ 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
Aşağıdaki yöntemle yapılır
for i in {1..10}; do for j in {a..c}; do echo $j$i; done; done| perl -pne "s/\n/ /g"
çıktı
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
listeye ekleyebilirsiniz .