मैं एक बैश शेल स्क्रिप्ट में 2 पैटर्न के बीच वर्णानुक्रमिक लाइनों को पसंद करता हूं।
निम्नलिखित इनपुट फ़ाइल को देखते हुए:
aaa
bbb
PATTERN1
foo
bar
baz
qux
PATTERN2
ccc
ddd
मुझे आउटपुट के रूप में उम्मीद है:
aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd
पसंदीदा उपकरण एक AWK "वन-लाइनर" है। सिड और अन्य समाधान भी स्वीकार किए जाते हैं। यदि स्पष्टीकरण शामिल है तो अच्छा होगा।
6 जवाब
यह asort()
का उपयोग करने के लिए एक सही मामला है जीएनयू जाग में एक सरणी को सॉर्ट करने के लिए:
gawk '/PATTERN1/ {f=1; delete a}
/PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]}
!f
f{a[$0]=$0}' file
यह एक समान तर्क का उपयोग करता है जैसे कि दो मार्कर पैटर्न के बीच की पंक्तियों का चयन कैसे करें जो कि जोड़ के साथ कई बार awk / sed हो सकती हैं बस यही है:
- इस सीमा के बाहर प्रिंट की लाइनें
- इस सीमा के भीतर स्टोर लाइनें
- और जब सीमा खत्म हो जाती है, तो उन्हें छाँटते हैं।
विस्तृत विवरण:
/PATTERN1/ {f=1; delete a}
PATTERN1 से मेल खाते हुए रेखा को खोजने पर, एक ध्वज को सेट करता है, और लाइनों की सरणी को साफ करता है।/PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]}
PATTERN2 से मेल खाते हुए लाइन ढूंढते समय, ध्वज को सेट करें। इसके अलावा, श्रेणी में सभी पंक्तियों वाले सरणीa[]
को छांटें और उन्हें प्रिंट करें।!f
यदि झंडा बंद है (जो कि सीमा के बाहर है), तो सही के रूप में मूल्यांकन करें ताकि लाइन मुद्रित हो।f{a[$0]=$0}
यदि झंडा चालू है, तो लाइन कोa[]
सरणी में स्टोर करें, ताकि बाद में इसकी जानकारी का उपयोग किया जा सके।
परीक्षा
▶ gawk '/PATTERN1/ {f=1} /PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]} !f; f{a[$0]=$0}' FILE
aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd
आप sed
और tail
के साथ sed
का उपयोग कर सकते हैं:
{
sed '1,/^PATTERN1$/!d' FILE
sed '/^PATTERN1$/,/^PATTERN2$/!d' FILE | head -n-1 | tail -n+2 | sort
sed '/^PATTERN2$/,$!d' FILE
} > output
पहली पंक्ति पहली पंक्ति से PATTERN1
तक सब कुछ प्रिंट करती है।
दूसरी पंक्ति PATTERN1
और PATTERN2
के बीच की रेखाओं को लेती है, अंतिम और पहली पंक्ति को हटाती है, और शेष रेखाओं को क्रमबद्ध करती है।
तीसरी पंक्ति फ़ाइल के अंत में PATTERN2
से सब कुछ प्रिंट करती है।
अधिक जटिल, लेकिन बहुत सारी लाइनों के भंडारण के मेमोरी लोड को कम कर सकता है (आपकी cfg फ़ाइल को इस बात के लिए बहुत बड़ा होना होगा, लेकिन फिर भी ...)। GNU awk और एक प्रकार के कॉपीप्रेशन का उपयोग करना:
gawk -v p=1 '
/^PATTERN2/ { # when we we see the 2nd marker:
# close the "write" end of the pipe to sort. Then sort will know it
# has all the data and it can begin sorting
close("sort", "to");
# then sort will print out the sorted results, so read and print that
while (("sort" |& getline line) >0) print line
# and turn the boolean back to true
p=1
}
p {print} # if p is true, print the line
!p {print |& "sort"} # if p is false, send the line to `sort`
/^PATTERN1/ {p=0} # when we see the first marker, turn off printing
' FILE
यह थोड़ा अपरंपरागत है लेकिन विम का उपयोग कर रहा है:
vim -c 'exe "normal /PATTERN1\<cr>jV/PATTERN2\<cr>k: ! sort\<cr>" | wq!' FILE
जहाँ \<cr>
एक गाड़ी वापसी है, CTRL - v फिर CTRL M के रूप में दर्ज किया गया है।
आगे की व्याख्या:
- विम सामान्य मोड का उपयोग करना,
/PATTERN1\<cr>
- पहले पैटर्न की खोज करेंj
- अगली पंक्ति पर जाएंV
- दृश्य मोड दर्ज करें/PATTERN2\<cr>
- दूसरे पैटर्न की खोज करेंk
- एक पंक्ति पर वापस जाएं: ! sort\<cr>
- आपके द्वारा चयनित दृश्य पाठ को क्रमबद्ध करेंwq!
- सहेजें और बाहर निकलें
जीएनयू sed का उपयोग करते हुए @choroba द्वारा प्रस्तावित समाधान की पंक्तियों के साथ, (Q
कमांड पर निर्भर करता है):
{
sed -n '1,/PATTERN1/p' FILE
sed '1,/PATTERN1/d; /PATTERN2/Q' FILE | sort
sed -n '/PATTERN2/,$p' FILE
}
स्पष्टीकरण:
'1,/PATTERN1/p'
और/PATTERN2/,$p
क्रमशःp
का उपयोग रेंज 1 से / PATTERN1 / समावेशी और ($
फ़ाइल के अंत में है) में एक रेखा प्रिंट करता है।-n
का उपयोग सभी लाइनों को प्रिंट करने के डिफ़ॉल्ट व्यवहार को अक्षम करता है।p
के संयोजन में उपयोगी।- मध्य रेखा में, पहली पंक्ति मिलान / PATTERN2 / पर {1 X0}} कमांड का उपयोग 1 से / PATTERN1 / और
Q
(मुद्रण के बिना छोड़ना, GNU sed केवल) के लिए लाइनों को हटाने के लिए किया जाता है। इन लाइनों को क्रमबद्ध किया जाना है, और इस प्रकारsort
में फीड किया जाता है।
स्पष्ट रूप से यह GNU AWK समाधान से नीच है, लेकिन सभी एक ही, यह एक GNU sed समाधान है:
sed '
/PATTERN1/,/PATTERN2/ {
/PATTERN1/b # branch/break if /PATTERN1/. This line is printed
/PATTERN2/ { # if /PATTERN2/,
x # swap hold and pattern spaces
s/^\n// # delete the leading newline. The first H puts it there
s/.*/sort <<< "&"/e # sort the pattern space by calling Unix sort
p # print the sorted pattern space
x # swap hold and pattern space again to retrieve PATTERN2
p # print it also
}
H # Append the pattern space to the hold space
d # delete this line for now - it will be printed in the block above
}
' FILE
ध्यान दें कि मैं e
/ पर भरोसा करता हूं > कमांड, एक GNU एक्सटेंशन।
परिक्षण:
▶ gsed '
/PATTERN1/,/PATTERN2/ {
/PATTERN1/b
/PATTERN2/ {
x
s/^\n//; s/.*/sort <<< "&"/ep
x
p
}
H
d
}
' FILE
aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd
संबंधित सवाल
जुड़े हुए प्रश्न
नए सवाल
bash
बैश कमांड शेल के लिए लिखी गई लिपियों के बारे में प्रश्नों के लिए। त्रुटियों / वाक्यविन्यास त्रुटियों के साथ शेल स्क्रिप्ट के लिए, कृपया यहां पोस्ट करने से पहले शेलचेक प्रोग्राम (या वेब शेलचेक सर्वर पर https://shellcheck.net) के साथ उन्हें जांचें। बैश के इंटरैक्टिव उपयोग के बारे में सवाल स्टैक ओवरफ्लो की तुलना में सुपर उपयोगकर्ता पर ऑन-टॉपिक होने की अधिक संभावना है।