Perluasan shell brace kanan-ke-kiri

9

Di zsh (dan shell lainnya), jika saya menyertakan argumen seperti (misalnya):

{a,b,c}{d,e,f}

ekspansi brace mengubahnya menjadi:

ad ae af bd be bf cd ce cf

Untuk tujuan saya, urutan argumen itu penting, dan saya perlu kawat gigi untuk melebar dari kanan ke kiri, bukan dari kiri ke kanan. Artinya, saya ingin ekspansi menjadi:

ad bd cd ae be ce af bf cf

Apakah ada cara untuk mengontrol urutan beberapa set kawat gigi diperluas? Saya mencari sesuatu yang akan bekerja dalam situasi apa pun, tidak hanya dengan argumen ini.

Michael Mrozek
sumber
Saya berasumsi Anda tidak tertarik pada solusi yang lebih kompleks yang melibatkan loop atau output yang diurutkan, kan?
terdon
@terdon Jika tidak ada cara lain saya kira; Saya berharap ada beberapa trik untuk mengubah urutan evaluasi ekspansi brace, tetapi mungkin tidak ada. Argumen-argumen itu hanyalah sebuah contoh, jadi sesuatu yang hanya {a,b,c}{d,e,f}bermanfaat
untuknya
Ya, saya juga menebak. Anda mungkin ingin memperjelas bahwa untuk menghindari jawaban berdasarkan urutan pengurutan.
terdon

Jawaban:

8

Anda dapat menggabungkan ekspansi parameter dengan ekspansi brace.

% foo=(d e f)
$ echo {a,b,c}${^foo}
ad bd cd ae be ce af bf cf

Jika Anda tidak ingin mendefinisikan foosecara terpisah (seperti yang tampaknya), Anda dapat menggunakan yang berikut:

$ echo {a,b,c}${^:-d e f}
ad bd cd ae be ce af bf cf

Jika Anda memiliki rcexpandparamopsi yang diset, maka Anda tidak perlu ^dalam salah satu contoh untuk mengaktifkan perilaku ini.

(Catatan: saat pengujian, saya juga memiliki shwordsplitopsi yang ditetapkan. Jika Anda tidak mengaturnya, maka cobalah, misalnya echo {a,b,c}${^=:-d e f}. Moral dari cerita: hampir semua hal mungkin terjadi zsh, tetapi Anda harus memastikan Anda menggunakan yang benar kombinasi opsi dan sintaks.)

chepner
sumber
1
Anda harus menggunakan print -- {a,b,c}${^=:-d e f}sebagai contoh utama, sejak kapan split+globdimatikan secara default di zsh.
cuonglm
4

Dalam zshAnda dapat menggunakan argumen -C jumlah kolom yang ditentukan untuk printmenyukai:

print $(print -C3 {a,b,c}{d,e,f})

...mendapatkan...

ad bd cd ae be ce af bf cf

... tanpa $IFSpemisahan berikut:

print -C3 {a,b,c}{d,e,f}

... mencetak ...

ad bd cd
ae be ce
af bf cf

... tetapi Anda dapat melakukannya melintasi sebelum turun seperti ...

print -aC3 {a,b,c}{d,e,f}

ad ae af
bd be bf
cd ce cf

...atau...

print $(print -aC2 {foo,bar}{bad,baz})

foobad foobaz barbad barbaz
mikeserv
sumber
Itu menghasilkan output yang sama dengan yang coba dihindari oleh MIchael. Dia ingin 1.1 2.1 3.1 dan Anda memberi 1.1 1.2 1.3 (jika itu jelas).
terdon
@terdon - poin bagus.
mikeserv
Saya menduga (meskipun tidak secara eksplisit dinyatakan) bahwa Michael mengincar urutan pemasangan yang spesifik. Pendekatan Anda hanya berfungsi jika elemen-elemen tersebut dapat diurutkan berdasarkan abjad. Bagaimana dengan mendapatkan foobad foobaz barbad barbazdari {foo, bar} {bad, baz} `?
terdon
@terdon - yah, kalau itu yang dia incar kenapa tidak bilang begitu? dan lagi pula, kolom dapat dipasangkan dengan cara apa pun jika Anda menghitungnya.
mikeserv
1
@terdon - Anda para moderator sepertinya membiasakan diri untuk mengatakan apa yang tidak Anda maksudkan.
mikeserv
2

Anda bisa meletakkan angka di akhir setiap elemen set kedua dan kemudian mengurutkan pada karakter terakhir:

echo -e "\n"{a,b,c}{d1,e2,f3} | sort -k 1.3 | cut -c 1-2 | tr '\n' ' '

Yang lebih baik adalah menambahkan angka setelah beberapa pemisah (spasi), untuk memotong bidang, bukan karakter:

echo -e "\n"{a,b,c}{"d 1","e 2","f 3"} | sort -k 2n | cut -f 1 -d ' ' -s | tr '\n' ' '
jimmij
sumber