`Sed` में, मैं एक स्ट्रिंग में वर्णों के बीच एक" और "कैसे रख सकता हूं?


जवाबों:


25

GNU के साथ sed:

sed 's/./\&&/2g'

( substitute हर g) ( ) अक्षर ( .) उसी के साथ ( &) से पहले &( \&) लेकिन केवल दूसरी घटना से शुरू ( 2)।

portably:

sed 's/./\&&/g;s/&//'

(हर घटना को प्रतिस्थापित करें, लेकिन फिर पहले को हटा दें &जो हम नहीं चाहते हैं)।

कुछ awkकार्यान्वयन के साथ (POSIX नहीं है क्योंकि व्यवहार एक खाली FS के लिए अनिर्दिष्ट है):

awk -F '' -v OFS="&" '{$1=$1;print}'

( gawkऔर कुछ अन्य awkकार्यान्वयनों के साथ, एक खाली फ़ील्ड विभाजक रिकॉर्ड को उसके चरित्र घटकों में विभाजित करता हैआउटपुट फ़ील्ड सेपरेटर ( OFS) के लिए सेट है &। हम $1नए फ़ील्ड इंस्ट्रक्टर के साथ पुन: उत्पन्न होने के लिए रिकॉर्ड करने के लिए बाध्य करने के लिए (स्वयं) के लिए एक मान प्रदान करते हैं। इसे प्रिंट करने से पहले, NF=NFयह काम भी करता है और कई आवक कार्यान्वयनों में थोड़ा अधिक कुशल होता है, लेकिन जब आप ऐसा करते हैं तो वर्तमान में पोसिक्स द्वारा अनिर्दिष्ट है)।

perl:

perl -F -lape '$_=join"&",@F' 

( -peहर पंक्ति के लिए कोड चलाता है, और परिणाम प्रिंट ( $_); -lस्ट्रिप्स और लाइन अंत स्वचालित रूप से फिर से कहते हैं, -aभरता @Fमें सीमांकक सेट पर इनपुट विभाजन के साथ -F।, जो यहाँ एक रिक्त स्ट्रिंग है परिणाम हर चरित्र में विभाजित करने के लिए है @F, फिर उन्हें 'और' के साथ मिलाएं, और लाइन प्रिंट करें।)

वैकल्पिक रूप से:

perl -pe 's/(?<=.)./&$&/g' 

(प्रत्येक वर्ण को बदलें, बशर्ते कि यह किसी अन्य वर्ण (लुक-रेगेक्स ऑपरेटर से पहले से जुड़ा हो? <= ...)

zshशेल ऑपरेटरों का उपयोग करना :

in=12345
out=${(j:&:)${(s::)in}}

(फिर, s::पैरामीटर विस्तार ध्वज का उपयोग करके एक खाली क्षेत्र विभाजक पर विभाजित करें और साथ जुड़ें &)

या:

out=${in///&} out=${out#?}

( ksh ऑपरेटर &का उपयोग करके कुछ भी नहीं (इसलिए हर वर्ण से पहले) की जगह लें ${var//pattern/replacement}(हालांकि kshएक खाली पैटर्न का मतलब कुछ और है, और फिर भी कुछ और, मुझे यकीन नहीं है कि क्या है bash), और POSIX ${var#pattern}स्ट्रिपिंग के साथ पहले एक को हटा दें ऑपरेटर)।

ksh93शेल ऑपरेटरों का उपयोग करना :

in=12345
out=${in//~(P:.(?=.))/\0&}

( ~(P:perl-like-RE)ksh93 ग्लोब ऑपरेटर होने के नाते perl जैसी नियमित अभिव्यक्तियों का उपयोग करना (perl या PCRE के अलग से अलग है), (?=.)लुक- फॉरवर्ड ऑपरेटर होने के नाते: एक चरित्र को बदलें, बशर्ते वह स्वयं के साथ एक और चरित्र ( \0) और &)

या:

out=${in//?/&\0}; out=${out#?}

(हर चरित्र को बदलें ?) ( &और खुद के साथ \0)

bashशेल ऑपरेटरों का उपयोग करना :

shopt -s extglob
in=12345
out=${in//@()/&}; out=${out#?}

(उसी रूप में zsh, सिवाय इसके कि आपको @()वहां (एक ksh ग्लोब ऑपरेटर जिसके लिए आपको आवश्यकता extglobहै bash) की आवश्यकता है )।


2
@AFSHIN, जो 012345इनपुट पर काम नहीं करेगा
स्टीफन चेज़लस

1
यह काम करना चाहिएawk -F '' -v OFS="&" 'NF=NF'
αғsнιη

1
@AFSHIN, लेकिन खाली लाइनों को हटा दें। आम तौर पर, जब किसी स्थिति के रूप में एक कार्रवाई का उपयोग करते हैं और कार्रवाई के परिणाम को मुद्रित करने का इरादा रखते हैं, तो आपको यह सुनिश्चित करने की आवश्यकता है कि कार्रवाई द्वारा लौटाए गए मान खाली स्ट्रिंग या संख्यात्मक स्ट्रिंग नहीं है जो कि 0. से हल होता है
स्टीफन चेज़लस

1
क्या आप इनमें से प्रत्येक का त्वरित विवरण जोड़ सकते हैं? ऐसा लगता है कि यहां सीखने के लिए कुछ भयानक चीजें हैं, लेकिन मुझे यह भी नहीं पता है कि मैं उनमें से अधिकांश पर शोध करना शुरू करूंगा कि उन्हें इस विशिष्ट समस्या के दायरे से बाहर कैसे लागू किया जाए।
IMSoP

1
@ स्टीफनचेज़ेलस ब्रिलियंट, धन्यवाद। सीड जैसी चीजों के लिए जटिल डॉक्स की खोज करना एक कला है, इसलिए कुछ हाथों के उदाहरण नए बिट्स सीखने का एक शानदार तरीका है जिन्हें आपने पहले नहीं देखा था।
IMSoP

15

यूनिक्स उपयोगिताओं:

fold -w1|paste -sd\& -

व्याख्या की:

"fold -w1" - प्रत्येक इनपुट चरित्र को अपनी लाइन में लपेटेगा

गुना - निर्दिष्ट चौड़ाई में फिट होने के लिए प्रत्येक इनपुट लाइन को लपेटें

-w, --width = WIDTH 80 के बजाय WIDTH कॉलम का उपयोग करें

%echo 12345|fold -w1
1
2
3
4
5

"paste -sd\& -"- &एक विभाजक के रूप में , इनपुट लाइनों को एक साथ मर्ज करेगा

पेस्ट - फ़ाइलों की मर्ज लाइनों

-s, - समानांतर में एक समय में एक फ़ाइल पेस्ट करें

-d, --delimiters = LIST TABs के बजाय LIST से वर्णों का पुन: उपयोग करता है

%fold -w1|paste -sd\& -
1&2&3&4&5

(ध्यान दें कि यदि इनपुट में कई लाइनें हैं, तो वे साथ जुड़ जाएंगे &)


2
मल्टीबीट पात्रों पर असफल। कोशिशecho "abcdeéèfg" | fold -1 | paste -sd\& -
इसहाक

3
@ ऐरो ज्यादातर शायद आप केवल गुना के एक छोटी गाड़ी के कोरुटिल्स संस्करण का उपयोग कर रहे हैं , जिसमें पूर्ण यूनिकोड समर्थन नहीं है। BSD फोल्ड, रेडहैट-पैचेड वर्जन ऑफ कोर्यूटिल्स (यानी फेडोरा या सेंटोस) के साथ-साथ बिजीबॉक्स कार्यान्वयन, यूनिकोड को बस अच्छे से संभाल सकता है।
ज़ेपेलिन

5
सवाल विशेष रूप से है sed
अलेक्जेंडर

6
@Alexander - यह सच है, और sedनीचे कई अच्छे उत्तर उपलब्ध हैं। और मुझे यह दिखाने में कोई बुराई नहीं है कि कार्य को अन्य तरीकों से कैसे हल किया जा सकता है।
ज़ेपेलिन

@ स्टीफनचैलेजलस> POSIXly, आपको फोल्ड -w 1 ट्रू चाहिए, मैंने जोड़ा है "-w", thx! "-"बदले में, आवश्यक नहीं हैIf no file operands are specified, the standard input shall be used
zeppelin


9
sed 's/\B/\&/g'

\ B - हर जगह मेल खाता है लेकिन एक शब्द सीमा पर; यदि यह मेल खाता है तो बाईं ओर वर्ण और दाईं ओर वर्ण दोनों "शब्द" वर्ण या "गैर-शब्द" वर्ण दोनों हैं।

जानकारी: GNU sed मैनुअल, रेगुलर एक्सप्रेशन एक्सटेंशन

परिक्षण:

sed 's/\B/\&/g' <<< '12345'
1&2&3&4&5

5
दिलचस्प विचार लेकिन सवाल यह नहीं कहता है कि स्ट्रिंग में एक स्थान, एक डॉट या कुछ भी नहीं है जो एक शब्द सीमा का गठन कर सकता है। यह सिर्फ "वर्णों के बीच" कहता है जिसे "किसी भी वर्ण" के रूप में व्याख्या की जानी चाहिए।
xhienne

4

यह कुछ अन्य उत्तरों की तुलना में थोड़ा धीमा होगा, लेकिन यह बहुत स्पष्ट है:

echo 12345 | perl -lnE 'say join "&", split //'

4

यहाँ एक और तरीका है। सीड एक्सप्रेशन का पहला भाग हर कैरेक्टर को कैप्चर करता है और उसके बाद कैरेक्टर और एंपर्सैंड के साथ बदल देता है। दूसरा भाग लाइन के अंत से एम्परसेंड को हटाता है।

echo 12345 | sed -r 's/(.)/\1\&/g;s/\&$//g'
1&2&3&4&5

मल्टीबाइट पात्रों पर भी काम करता है।


1
sedदो बार कॉल करने की आवश्यकता नहीं , एक sedस्क्रिप्ट में कई कमांड हो सकते हैं:sed -r 's/(.)/\1\&/g; s/\&$//g'
xhienne

xhienne, धन्यवाद, टीआईएल! उत्तर अपडेट किया गया।
अलेक्जेंडर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.