awk या sed को लोअरकेस / अपरकेस में स्ट्रिंग में केवल एक वर्ण?


13

क्या कोई तरीका है कि किसी स्ट्रिंग में केवल एक वर्ण को अपरकेस / लोअरकेस कैसे करें?

इनपुट उदाहरण:

syslog_apr_24_30
syslog_mar_01_17

वांछित उत्पादन:

syslog_Apr_24_30
syslog_Mar_01_17

ध्यान दें कि महीने की शुरुआत अपरकेस है।

मैंने कोशिश की है, awkलेकिन मैं इसे काम करने के लिए पर्याप्त नहीं हूं।

जवाबों:


18

आप \uGNU sed में एक अक्षर को अपरकेस करने के लिए उपयोग कर सकते हैं :

sed -e 's/_\(.\)/_\u\1/' input

पर्ल भी ऐसा ही करता है:

perl -pe 's/_(.)/_\u$1/' input

\l इसके विपरीत करता है।


8
एक स्पर्श सरल:sed 's/_./\U&/'
ग्लेन जैकमैन


3

Awk सबस्ट्रिंग और टॉपर के साथ संस्करण

awk 'BEGIN{ FS=OFS="_"} {
        cap=toupper(substr($2,1,1));
        lower=substr($2,2,3);
        $2 = cap lower; print 
}' list.txt 

नमूना रन:

$ awk 'BEGIN{ FS=OFS="_"} { 
    cap=toupper(substr($2,1,1));
    lower=substr($2,2,3);$2 = cap lower; print 
}' list.txt               
syslog_Apr_24_30
syslog_Mar_01_17

3

का उपयोग कर awk:

awk -F_ '{
    printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"
}' foo

या

awk -F_ '{
    for(i=1;i<=NF;i++) {
        if(i==2){
            printf "%s",toupper(substr($i,1,1))substr($i,2,length($i)-1)
        } 
        else {printf "%s",$i} 
        if(i<NF) {printf "%s","_"}
    } printf "%s","\n"}' foo

उदाहरण

% cat foo
syslog_apr_24_30
syslog_mar_01_17

% awk -F_ '{for(i=1;i<=NF;i++) {if(i==2){printf "%s",toupper(substr($i,1,1))substr($i,2,length($i)-1)} else {printf "%s",$i} if(i<NF) {printf "%s","_"}} printf "%s","\n"}' foo
syslog_Apr_24_30
syslog_Mar_01_17

% awk -F_ '{printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"}' foo 
syslog_Apr_24_30
syslog_Mar_01_17

3

यहाँ एक पर्ल दृष्टिकोण है:

$ perl -pe 's/_./uc($&)/e' file
syslog_Apr_24_30
syslog_Mar_01_17

-pद्वारा दी गई स्क्रिप्ट को लागू करने के बाद प्रत्येक पंक्ति को मुद्रित करने का कारण बनता है -e। प्रतिस्थापन पहले उदाहरण _और चरित्र का अनुसरण करता $&है, जो स्वयं के साथ होता है ( जो कुछ भी मिलान किया गया था) ऊपरी आवरण ( uc()), eप्रतिस्थापन ऑपरेटर के अंत में ( s///e) अभिव्यक्ति का मूल्यांकन करने के लिए आवश्यक है।



1

शुद्ध बैश 4.x, जिस भाग को आप ऊपर उठाना चाहते हैं, और ^^उस भाग के ऊपर के भाग को निकालने के लिए एक रेक्सक्स का उपयोग करते हैं। पूरे स्ट्रिंग को फिर से बनाने के लिए आगे और पीछे की तरफ से मिलान (* द्वारा मिलान किया गया):

foo=syslog_apr_24_30
if [[ $foo =~ (.*)(_[a-z])(.*) ]]; then
    foo=${BASH_REMATCH[1]}${BASH_REMATCH[2]^^}${BASH_REMATCH[3]}
fi

यदि आपको सभी उद्धृत नियम याद नहीं हैं, तो regex को छोड़कर सब कुछ उद्धृत करना सुरक्षित है (जो =~शाब्दिक स्ट्रिंग-मैच करेगा)।

ऊपर ^चढ़ने वाला पहला ऑपरेटर केवल एक चर (या सरणी तत्व) की शुरुआत में काम करता है। और ऐसा कोई विकल्प विस्तार प्रतीत नहीं होता है जो आपको यह बताता है कि perl एक लवल्यू कहेगा (जिसे आप असाइन / संशोधित कर सकते हैं)। अप / डाउनकेस-प्रथम ऑपरेटर एक ऐसा पैटर्न ले सकते हैं जो कि प्रति-चरित्र के आधार पर मेल खाता है, लेकिन यह ओवर स्किप करने में मदद नहीं करता है syslog_, क्योंकि ऐसे महीने के नाम हैं जो "syslog" में वर्णों से शुरू होते हैं।

वैसे भी, यह foo="$(echo "$foo" | sed 's/_./\U&/')"(ग्लेन जैकमैन द्वारा स्वीकृत उत्तर के लिए एक टिप्पणी के रूप में पोस्ट) से तेज हो सकता है ।

बैश, sed, या awk पर्ल की तुलना में कई गुना तेज होगा। यदि आप शेल लिपि में उपयोगी कई पर्ल वन-लाइनर्स ढूंढना शुरू करते हैं, तो आपको पूरी बात पर्ल में लिखनी चाहिए।


0

यदि महीना हमेशा पहले "_" (अंडरस्कोर) का अनुसरण करता है, तो इसका उपयोग करें (जैसा कि अन्य उत्तरों में दिखाया गया है):

sed -e 's/_\(.\)/_\u\1/'

यदि महीने से पहले अन्य अंडरस्कोर हो सकते हैं तो ऊपर काम नहीं करेगा।

यदि माह हमेशा 8 वें वर्ण से शुरू होता है, तो इसका उपयोग करें:

sed -e 's/^\(.\{7\}\)\(.\)/\1\u\2/'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.