उदाहरण के लिए {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
इस विशेष मामले के लिए, मुझे लगता है कि स्टीफन चेज़लस द्वारा दिया गया विकल्प सबसे अच्छा है।
दूसरी ओर, जब आप अधिक जटिल चीजों का विस्तार करते हैं, तो यह विकल्प अच्छा नहीं होता है। तो, आप इसे प्राप्त कर सकते हैं:
$ printf '%s\0' {a..c}{1..3} | sort -zk 1.2,1.2 | tr '\0' ' '
कौन सा रिटर्न:
a1 b1 c1 a2 b2 c2 a3 b3 c3
थोड़ा गड़बड़ लगता है, लेकिन अब, मेरे पास आदेश में एक बड़ा नियंत्रण है, बस ऊपर दिए गए कमांड में दो चार्ट बदल रहा है; उदाहरण के लिए:
$ 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
:
$ 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
तीसरे विस्तार में सभी चाहता हूं , तो 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
चौथे विस्तार में सभी चाहिए , तो 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
नोट 1 : आमतौर पर, यदि यह अंतिम विस्तार तर्कों की सूची के रूप में उपयोग किया जा रहा है, तो अनुगामी स्थान कोई समस्या नहीं है; लेकिन अगर आप इससे छुटकारा पाना चाहते हैं, तो आप ऊपर दिए गए किसी भी आदेश में जोड़ सकते हैं, उदाहरण के लिए| sed 's/ $//'
; या फिर| sed 's/ $/\n/'
, एक के लिए उस अनुगामी स्थान को बदलने के लिएnewline
नोट 2 : ऊपर के उदाहरणों में, मैं दो तत्वों के उपसमुच्चय का उपयोग करता हूं (जैसे: {a, b} और {1,2} ) केवल अवधारणा के प्रमाण में सरलता के लिए: आप किसी भी परिमित लंबाई के सबसेट का उपयोग कर सकते हैं, और संगत आदेश, तुलनीय होगा।
एक लाइनर जो काम करता है (बैश, ksh, zsh) (सभी गोले रिवर्स में "ब्रेस विस्तार" कर सकते हैं):
$ 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
निष्पादित कमांड (विस्तार के बाद) वास्तव में है 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
। आप जो आदेश चाहते हैं, उसे पाने के लिए आपको ऊपर की थोड़ी लंबी अभिव्यक्ति का उपयोग करना होगा।
एक लूप का उपयोग करना:
for n in {1..3}; do printf '%s\n' {a..c}"$n"; done
यह आपके पहले विस्तार के माध्यम से लूप करेगा और फिर दूसरे के साथ प्रत्येक वर्ण का विस्तार करेगा।
यदि आपको एक पंक्ति में सभी आउटपुट की आवश्यकता है, तो आप इसे हटा सकते हैं \n
:
for n in {1..3}; do printf '%s ' {a..c}"$n"; done
यह आपको एक अनुगामी न्यूलाइन नहीं देगा, लेकिन यदि आप इसे एक कमांड या वैरिएबल पर भेज रहे हैं जो कि एक समस्या नहीं होनी चाहिए।
यह आपके सरल मामले के लिए काम करता है और इसे बढ़ाया जा सकता है, लेकिन यह जल्दी से हाथ से निकल जाएगा। अधिक जटिल मामले जिनके लिए यह काम नहीं करेगा निर्माण के लिए आसान है।
ब्रेस विस्तार के क्रम को उल्टा करें, फिर पात्रों को स्वैप करें:
echo {1..3}{a..c} | sed -E 's/(.)(.)( ?)/\2\1\3/g'
एक सरल तरीका यह होगा कि आप सॉर्ट का उपयोग करें (1.2,1.2 का मतलब है कि आप एक पात्र को दूसरी स्थिति में ले जाते हैं और उसी स्थान पर समाप्त होते हैं)।
$ 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
यदि आप उन्हें एक पंक्ति में चाहते हैं, तो आप 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
सूची में भी जोड़ सकते हैं ।