it-swarm.com.de

Wenden Sie die Klammererweiterung in "umgekehrter Reihenfolge" an.

Zum Beispiel wird {a..c}{1..3} Zu a1 a2 a3 b1 b2 b3 c1 c2 c3 Erweitert.

Wenn ich a1 b1 c1 a2 b2 c2 a3 b3 c3 Drucken wollte, gibt es eine analoge Möglichkeit, dies zu tun? Was ist der einfachste Weg?

Du könntest es tun:

$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3

Was dann die Shell anweist, zu bewerten:

echo {a..c}1 {a..c}2 {a..c}3
30

Für diesen speziellen Fall denke ich, dass die von Stéphane Chazelas gegebene Option die beste ist.

Wenn Sie jedoch komplexere Dinge erweitern, lässt sich diese Option nicht gut skalieren. So können Sie dasselbe erreichen:

$ printf '%s\0' {a..c}{1..3} | sort -zk 1.2,1.2 | tr '\0' ' '

was zurückgibt:

a1 b1 c1 a2 b2 c2 a3 b3 c3

Scheint ein wenig chaotisch, aber jetzt habe ich eine große Kontrolle in der Reihenfolge, indem ich nur zwei Zeichen im obigen Befehl ändere; zum Beispiel:

$ echo {a..b}{1..2}{a..b}{1..2}

dies wird erweitert auf:

a1a1 a1a2 a1b1 a1b2 a2a1 a2a2 a2b1 a2b2 b1a1 b1a2 b1b1 b1b2 b2a1 b2a2 b2b1 b2b2

Angenommen, ich möchte alle 1 in der zweiten Erweiterung, dann die 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

Angenommen, ich möchte alle a in der dritten Erweiterung, dann die 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

Angenommen, ich möchte alle 1 in der vierten Erweiterung, dann die 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

Angenommen, ich möchte alle 1a in der Mitte, dann 1b, dann 2a, dann 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

Sie können sogar genauso einfach eine beliebige Reihenfolge in den obigen Erweiterungen umkehren, indem Sie dem vorherigen Befehl ein r hinzufügen. Zum Beispiel der letzte:

$ 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 : Wenn diese endgültige Erweiterung als Liste von Argumenten verwendet werden soll, ist der nachfolgende Leerzeichen normalerweise kein a Problem; Wenn Sie es jedoch entfernen möchten, können Sie zu jedem der oben genannten Befehle beispielsweise | sed 's/ $//'; oder sogar | sed 's/ $/\n/', um diesen nachgestellten Leerzeichen für ein newline zu ändern

Note_2 : In den obigen Beispielen habe ich Teilmengen von zwei Elementen verwendet (dh: {a, b} und {1,2} ) nur zur Vereinfachung des Proof of Concept: Sie können Teilmengen beliebiger endlicher Länge verwenden, und der entsprechende Befehl wäre vergleichbar.

10
matsib.dev

bash, ksh, zsh

Ein Einzeiler, der funktioniert (bash, ksh, zsh) (nicht alle Shells können "Brace Expansion" in umgekehrter Reihenfolge ausführen):

$ echo {3..1}{c..a} | rev
a1 b1 c1 a2 b2 c2 a3 b3 c3

Eine Alternative, die eval verwendet (was immer noch für bash, ksh, zsh gilt und möglicherweise kryptischer ist), ist:

$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3

Um zu verstehen, was passiert, ersetzen Sie eval durch echo:

$ echo echo '{a..c}'{1..3}
echo {a..c}1 {a..c}2 {a..c}3

Der ausgeführte Befehl (nach evaler Erweiterung) lautet tatsächlich echo {a..c}1 {a..c}2 {a..c}3. Welches erweitert sich, wie Sie wollen/brauchen.

alle Muscheln

Es gibt mehrere Muscheln ohne "Klammererweiterungen", daher ist es nicht möglich, diese für "alle Muscheln" zu verwenden. Wir brauchen eine Schleife (mit einem nachgestellten Leerzeichen):

$ 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 

Wenn Sie keinen nachgestellten Speicherplatz hinzugefügt haben müssen:

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

Druckt

a1 b1 c1 a2 b2 c2 a3 b3 c3

Wenn Sie dies für viele Werte tun müssen, müssen Sie etwas Ähnliches wie die Klammererweiterung verwenden, um eine Liste von Zahlen $(seq 10) zu generieren. Und da seq keine Liste von Buchstaben generieren kann, müssen wir die generierten Zahlen in ASCII konvertieren:

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

drucke:

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

Die Klammererweiterungen in {a..c}{1..3} Werden von links nach rechts erweitert, sodass Sie zuerst a{1..3} b{1..3} c{1..3} Erhalten und dann die Buchstaben mit den Zahlen zu a1 a2 a3 b1 b2 b3 c1 c2 c3 Kombiniert werden. Um die gewünschte Reihenfolge zu erhalten, müssen Sie den etwas längeren Ausdruck oben verwenden.

3
Kusalananda

Dies funktioniert für Ihren einfachen Fall und kann erweitert werden, würde aber schnell außer Kontrolle geraten. Komplexere Fälle, für die dies nicht funktionieren würde, sind einfach zu konstruieren.

Kehren Sie die Reihenfolge der Klammererweiterungen um und tauschen Sie dann die Zeichen aus:

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

Verwenden einer Schleife:

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

Dies durchläuft Ihre erste Erweiterung und erweitert dann jedes Zeichen mit dem zweiten.

Wenn Sie die Ausgabe alle in einer Zeile benötigen, können Sie den \n Entfernen:

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

Dies gibt Ihnen keine nachfolgende neue Zeile, aber wenn Sie sie an einen Befehl oder eine Variable übergeben, sollte dies kein Problem sein.

2
jesse_b

Eine einfache Methode wäre die Verwendung der Sortierung (1.2,1.2 bedeutet, dass Sie ein Zeichen an der zweiten Position nehmen und an derselben Stelle enden).

$ 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

Wenn Sie sie in einer Zeile haben möchten, können Sie tr wie folgt verwenden:

$ 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