tr -c \\n 1 <testfile | #first transform every [^\n] char to a 1
grep -nF '' | #next get line numbers
paste -d: - testfile | #then paste it together with itself
sort -t: -nk2,2 #then sort on second field
... और विजेता है ... पंक्ति 2, ऐसा प्रतीत होगा।
2:1111:4for
4:11111:five!
1:1111111:seven/7
3:11111111:8 eight?
लेकिन इसके साथ समस्या यह है कि हर पंक्ति को काम करने के लिए लंबाई में दोगुनी से अधिक होनी चाहिए - ताकि LINE_MAX प्रभावी रूप से आधा हो। कारण यह है कि यह उपयोग कर रहा है - क्या, एक आधार 1? - लाइन की लंबाई का प्रतिनिधित्व करने के लिए। एक समान - और शायद अधिक सुव्यवस्थित - दृष्टिकोण उस जानकारी को स्ट्रीम में संपीड़ित करने के लिए हो सकता है। मेरे साथ होने वाली उन पंक्तियों के साथ पहला विचार unexpand
यह है कि मुझे यह करना चाहिए :
tr -c \\n \ <testfile | #transform all [^\n] to <space>
unexpand -t10 | #squeeze every series of 10 to one tab
grep -nF '' | #and get the line numbers
sed 's/:/!d;=;:/;h;:big #sed compares sequential lines
$P;$!N; /\(:[^ ]*\)\( *\)\n.*\1.*\2/!D #newest line is shorter or...
g;/:./!q;b big' | #not; quit input entirely for blank line
sed -f - -e q testfile #print only first occurrence of shortest line
वह प्रिंट करता है ...
2
4for
एक और, बस sed
:
sed -n '/^\n/D;s/\(.\)\(\n.*\)*/\1/g
$p;h; s// /g;G;x;n;//!g;H;s// /g
G; s/^\( *\)\(\n \1 *\)\{0,1\}\n//
D' <infile >outfile
वाक्यविन्यास मानकों का अनुपालन है - लेकिन यह कोई गारंटी नहीं है कि कोई भी पुराना सही ढंग से sed
संभाल लेगा \(reference-group\)\{counts\}
- कई नहीं।
यह मूल रूप से एक ही regexp को बार-बार इनपुट पर लागू करता है - जो कि उन्हें संकलित करने का समय होने पर बहुत फायदेमंद हो सकता है। वह पैटर्न है:
\(.\)\(\n.*\)*
जो अलग-अलग तरीके से अलग-अलग तार से मेल खाता है। उदाहरण के लिए:
string1\nstring2\nstring3
... s
में \1
और ''
शून्य स्ट्रिंग के साथ मिलान किया गया है \2
।
1\nstring2\nstring3
... 1
में \1
और के साथ मेल खाता \nstring2\nstring3
है\2
\nstring2\nstring3
... \n
में \1
और ''
शून्य स्ट्रिंग के साथ मिलान किया गया है \2
। यह समस्याग्रस्त होगा यदि \n
पैटर्न स्पेस के सिर पर होने वाली ईवलाइन का कोई भी मौका था - लेकिन इसे रोकने के लिए कमांड /^\n/D
और //!g
कमांड का उपयोग किया जाता है। मैंने उपयोग किया, [^\n]
लेकिन इस छोटी सी स्क्रिप्ट के लिए अन्य जरूरतों ने पोर्टेबिलिटी को एक चिंता का विषय बना दिया और मैं कई मायनों में संतुष्ट नहीं था, जिसे अक्सर गलत समझा जाता है। साथ ही, .
तेज है।
\nstring2
string1
... मैच \n
और s
फिर में \1
और दोनों में ''
शून्य स्ट्रिंग मिलता है \2
। खाली लाइनें बिल्कुल मेल नहीं खाती हैं।
जब पैटर्न को दो g
पक्षपाती रूप से लागू किया जाता है - दोनों बाएं-सबसे मानक पूर्वाग्रह और कम दाएं-साइड \n
ईलाइन बायस - एक स्किप को प्रभावित करने के लिए काउंटर-संतुलित होते हैं। कुछ उदाहरण:
s/\(.\)\(\n.*\)*/\1:\2/g
s/\(.\)\(\n.*\)*/\2\1:/g
s/\(.\)\(\n.*\)*/\1: /g
s/\(.\)\(\n.*\)*/ :\2/g
... यदि सभी निम्नलिखित स्ट्रिंग के लिए (उत्तराधिकार में नहीं) लागू होते हैं ...
string1\nstring2
... इसे बदल देंगे ...
s:t:r:i:n:g:1:\nstring2
s:t:r:i:n:g:\nstring21:
s:t:r:i:n:g:1:
: : : : : : :\nstring2
मूल रूप से मैं regexp का उपयोग हमेशा किसी भी पैटर्न-स्पेस में केवल पहली पंक्ति को संभालने के लिए करता हूं जिससे मैं इसे लागू करता हूं। यह मुझे दोनों बनाए रखने वाले शॉर्ट-मैच-अब तक लाइन के दो अलग-अलग संस्करणों को हथकंडा करने में सक्षम बनाता है और सबसे हाल ही में लाइन का उपयोग करने के लिए परीक्षण छोरों का सहारा लिए बिना - हर प्रतिस्थापन लागू एक ही बार में पूरे पैटर्न-स्थान को संभालता है।
शाब्दिक स्ट्रिंग / स्ट्रिंग तुलना के लिए अलग-अलग संस्करण आवश्यक हैं - इसलिए प्रत्येक पंक्ति का एक संस्करण होना चाहिए जहां सभी वर्ण समान होने की गारंटी है। लेकिन निश्चित रूप से अगर एक या दूसरे को वास्तव में इनपुट में सबसे छोटी लाइन हो रही है, तो आउटपुट के लिए मुद्रित लाइन को संभवतः लाइन का मूल संस्करण होना चाहिए - न कि जिसकी तुलना के लिए मैंने सैनिटाइज्ड / होमोजेनाइज्ड किया है। और इसलिए मुझे प्रत्येक के दो संस्करण चाहिए।
यह दुर्भाग्यपूर्ण है कि एक और आवश्यकता एक ही संभालने के लिए बहुत सारे बफर स्विचिंग है - लेकिन कम से कम न तो बफर वर्तमान में रहने के लिए आवश्यक चार लाइनों से अधिक है - और इसलिए शायद यह भयानक नहीं है।
वैसे भी, प्रत्येक चक्र के लिए पहली चीज जो याद की गई रेखा पर परिवर्तन है - क्योंकि वास्तव में बचाई गई एकमात्र प्रति शाब्दिक है - ...
^ \nremembered line$
... और बाद में n
एक्सट्रीम इनपुट लाइन किसी भी पुराने बफर को ओवरराइट कर देती है। यदि इसमें कम से कम एक वर्ण नहीं है तो इसे प्रभावी रूप से अनदेखा कर दिया जाता है। यह q
पहली बार होने वाली ब्लैंक लाइन पर यूट करने के लिए बहुत आसान होगा , लेकिन, ठीक है, मेरे टेस्ट डेटा में बहुत सारे थे और मैं कई पैराग्राफ को संभालना चाहता था।
और इसलिए यदि इसमें एक वर्ण समाहित है तो इसका शाब्दिक संस्करण याद की गई रेखा से जुड़ा है और इसका स्पेसिफाइड तुलना संस्करण इस तरह से पैटर्न स्पेस के प्रमुख पर स्थित है:
^ \n \nremembered line\nnew$
अंतिम प्रतिस्थापन उस पैटर्न स्पेस पर लागू होता है:
s/^\( *\)\(\n \1 *\)\{0,1\}\n//
इसलिए यदि नई लाइन में याद रखने वाली लाइन को फिट करने के लिए आवश्यक जगह हो सकती है, तो कम से कम एक चार को छोड़े जाने के लिए पहले दो पंक्तियों को प्रतिस्थापित किया जाता है, केवल पहले को।
परिणाम की परवाह किए बिना पैटर्न स्पेस में पहली पंक्ति को D
फिर से शुरू करने से पहले हमेशा एंड-ऑफ-साइकिल पर eleted किया जाता है। इसका मतलब है कि अगर नई लाइन पिछले स्ट्रिंग से छोटी है ...
new
... चक्र में पहले प्रतिस्थापन के लिए वापस भेजा जाता है जो हमेशा केवल पहली नईलाइन चार पर से पट्टी करेगा - और इसलिए यह संपूर्ण रहता है। लेकिन अगर यह नहीं है तो स्ट्रिंग ...
remembered line\nnew
... इसके बजाय अगला चक्र शुरू होगा, और पहले प्रतिस्थापन स्ट्रिंग से यह पट्टी करेगा ...
\nnew
...हर बार।
अंतिम पंक्ति में याद की गई पंक्ति को मानक के रूप में प्रिंट किया जाता है, और इसलिए दिए गए उदाहरण के डेटा के लिए, यह प्रिंट करता है:
4for
लेकिन, गंभीरता से, उपयोग करें tr
।