केवल बैश में, कोई बाहरी आदेश नहीं:
str="foobarbazblargblurg"
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
या एक-लाइन पाइप संस्करण के रूप में:
echo foobarbazblargblurg |
{ IFS= read -r str; [[ $str =~ ${str//?/(.)} ]]; \
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"; }
जिस तरह से यह काम करता है वह स्ट्रिंग के प्रत्येक चरित्र को रेगेक्स मैच के लिए "(।)" में परिवर्तित करने और =~
फिर कैप्चर करने के लिए होता है , फिर BASH_REMATCH[]
आवश्यकता के अनुसार समूह से कैप्चर किए गए एक्सप्रेशंस को आउटपुट करता है। लीडिंग / ट्रेलिंग / इंटरमीडिएट रिक्त स्थान संरक्षित हैं, "${BASH_REMATCH[@]:1}"
उन्हें छोड़ने के लिए आसपास के उद्धरण हटा दें ।
यहाँ इसे एक फंक्शन में लपेटा गया है, अगर कोई तर्क नहीं है, तो यह अपने तर्कों को पढ़ेगा या स्टड को पढ़ेगा:
function fmt4() {
while IFS= read -r str; do
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
done < <( (( $# )) && printf '%s\n' "$@" || printf '%s\n' $(< /dev/stdin) )
}
$ echo foobarbazblargblurg | fmt4
foob arba zbla rgbl urg
आप प्रारूप स्ट्रिंग को तदनुसार समायोजित करने के लिए आसानी से गणना को पैरामीटर कर सकते हैं।
एक अनुगामी स्थान जोड़ा जाता है, printf
यदि समस्या है तो एक के बजाय दो एस का उपयोग करें :
printf "%s%s%s%s" "${BASH_REMATCH[@]:1:4}"
(( ${#BASH_REMATCH[@]} > 5 )) && printf " %s%s%s%s" "${BASH_REMATCH[@]:5}"
printf
पहले 4 अक्षरों के लिए पहला प्रिंट (दूसरा), दूसरा सशर्त सभी (यदि कोई है) समूहों को अलग करने के लिए एक अग्रणी स्थान के साथ प्रिंट करता है। परीक्षण 5 तत्वों के लिए है न कि 4 शून्य तत्व के लिए।
टिप्पणियाँ:
- शेल
printf
का %c
उपयोग इसके बजाय किया जा सकता है %s
, %c
(हो सकता है) इरादे को स्पष्ट करता है, लेकिन यह बहु-बाइट वर्ण सुरक्षित नहीं है। यदि आपका बैश का संस्करण सक्षम है, तो उपरोक्त सभी मल्टी-बाइट चरित्र सुरक्षित है।
- शेल
printf
अपने प्रारूप स्ट्रिंग का तब तक पुन: उपयोग करता है जब तक कि वह तर्कों से बाहर नहीं निकल जाता है, इसलिए यह एक बार में 4 तर्कों को पकड़ लेता है, और अनुगामी तर्कों को संभालता है (इसलिए कोई किनारे के मामलों की आवश्यकता नहीं है, यहां कुछ अन्य उत्तरों के विपरीत जो यकीनन गलत हैं)
BASH_REMATCH[0]
संपूर्ण मिलान स्ट्रिंग है, इसलिए केवल इंडेक्स 1 से शुरू होने वाला आउटपुट
printf -v myvar ...
एक वैरिएबल को स्टोर करने के बजाय उपयोग करें myvar
(सामान्य रीड-लूप / सब्स्क्रिप्शन व्यवहार के अधीन)
printf "\n"
यदि आवश्यक हो तो जोड़ें
zsh
यदि आप match[]
इसके बजाय सरणी का उपयोग करते हैं, तो आप उपरोक्त कार्य कर सकते हैं BASH_REMATCH[]
, और सभी अनुक्रमितों में से 1 घटा zsh
सकते हैं क्योंकि पूरे मैच में 0 तत्व नहीं है।
sed
मैं पहले कोशिश कर रहा था के करीब था, मैं खुद को लात मार सकता था।