सवाल मैं 2 प्रतीकों के बीच पाठ की एक श्रृंखला को कैसे संपादित कर सकता हूं? अजीब, sed, regex


"*" प्रतीक का उपयोग करके, (यह होना आवश्यक नहीं है, किसी भी विशेष चरित्र को इंगित करने के लिए किया जाएगा), मैं इस से टेक्स्ट कैसे संपादित कर सकता हूं:

*berry
straw
rasp
blue
boysen
*
blahblah
blahblah
blahblah
*berry
straw
blue
*
blah
*table
vege
pingpong
*

इसके लिए:

strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable

पहले मिलान तारांकन के बाद प्रत्येक चरित्र को प्रत्येक लाइन पर रखा जाएगा जब तक कि द्वितीय तारांकन मैच नहीं मिलता है।

इस बारे में कोई भी लीड मैं इस बारे में कैसे जा सकता हूं? (sed या awk को प्राथमिकता दी जाएगी, लेकिन यदि आप किसी अन्य तरीके से सोच सकते हैं, तो कृपया मुझे अपना कोड शूट करें!)

मुझे पता है कि तारों वाली सभी रेखाओं को कैसे हटाया जाए, यह सिर्फ चरित्र प्लेसमेंट भाग है जिसे मैं नहीं सोच सकता


6
2018-04-25 01:49


मूल




जवाब:


इस awk कोड पर्याप्त हो सकता है:

awk -F'*' 'NF == 2 {label = $2; next} {$0 = $0 label} 1'

इसे तोड़ने के लिए:

  • उपयोग * क्षेत्र विभाजक के रूप में। इस तरह, हम बस खेतों की संख्या की जांच कर सकते हैं (NF) यह निर्धारित करने के लिए कि ब्लॉक की शुरुआत या अंत तक पहुंच गया है या नहीं।
  • जब दो फ़ील्ड होते हैं, तो हम दूसरे फ़ील्ड को सहेजते हैं label और अगली पंक्ति में जारी रखें।
  • तब से, हम इसे जोड़ते हैं label वर्तमान रेखा के लिए, और फिर प्रिंट करें। यदि लेबल खाली है, तो हम एक ब्लॉक के बाहर हैं और इसका कोई प्रभाव नहीं है। यदि नहीं, तो हमें आवश्यक आउटपुट मिलता है।

12
2018-04-25 02:07



बिल्कुल आश्चर्यजनक, बस मैं जो खोज रहा था। मुझे हटाने की फ़ाइलों की भी आवश्यकता नहीं थी, क्योंकि आउटपुट सिर्फ वही था जो मैं चाहता था। महान स्पष्टीकरण के लिए भी धन्यवाद। चीयर्स, एक अच्छा है! - TuxForLife
मैं बहुत अधिक प्यार करता हूँ: 3 - Sergiy Kolodyazhnyy


में sed, आप इसे हटाने से पहले "विशेष" रेखा को होल्ड स्पेस में कॉपी कर सकते हैं

sed -e '/^\*/{h;d;}'

और उसके बाद परिणामस्वरूप नई लाइन और मार्कर वर्ण को बदलकर, प्रत्येक सफल पैटर्न स्थान पर होल्ड स्पेस को संलग्न करें

    -e '{G;s/\n\*//;}'

अपने डेटा के साथ परीक्षण,

$ sed -e '/^\*/{h;d;}' -e '{G;s/\n\*//;}' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable

नोट: यह तब नहीं रुकता जब यह दूसरे तारांकन से मुकाबला करता है; यह बिल्कुल वही करता है, लेकिन यह संलग्न है * इसके बाद कुछ भी नहीं - जब तक यह अगले मैच से मेल नहीं खाता *sometext


8
2018-04-25 02:09



दिलचस्प है, मैंने कभी भी "होल्ड स्पेस" रणनीति नहीं देखी है, sed में नए पाठ के लिए धन्यवाद। आपका कोड पूरी तरह से मेरी फाइल के साथ भी काम करता है, धन्यवाद, आपका दिन अच्छा है! - TuxForLife


यहां एक पर्ल तरीका है:

$ perl -lne '/^\*(.*)/ || print "$_$1"' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable

व्याख्या

-n पर्ल को इनपुट फ़ाइल की प्रत्येक पंक्ति को पढ़ने के लिए, विशेष चर में सहेजने का कारण बन जाएगा $_, द -l यह मुझे कारण होगा) पीछे की रेखाओं को पीछे छोड़ना (\n) प्रत्येक लाइन से और ii) प्रत्येक कॉल में एक नई लाइन जोड़ें print-e वह स्क्रिप्ट है जो प्रत्येक पंक्ति पर लागू होती है।

  • /^\*(.*)/ : मैच लाइनें जो तारांकन से शुरू होती हैं और तारांकन के बाद सबकुछ बचाती हैं $1 (यही है कि कोष्ठक क्या करते हैं)।

  • || print "$_$1"' : द || एक तार्किक है OR। इसलिए print केवल तभी निष्पादित किया जाएगा जब वर्तमान रेखा तारांकन से शुरू नहीं हुई है। यदि ऐसा है, तो हम वर्तमान लाइन मुद्रित करते हैं ($_) जो भी वर्तमान में बचाया गया है के साथ $1 (तारांकन के बाद पैटर्न)।


हमेशा की तरह, ऐसा करने के कई तरीके हैं। एक मूर्ख और अक्षम, लेकिन जो शेल की स्ट्रिंग मैनिपुलेशन क्षमताओं को हाइलाइट करता है, वह है:

$ while read line; do 
    [[ $line =~ ^\* ]] && pat="${line#\*}" || printf "%s%s\n" "$line" "$pat"; 
  done < file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable

व्याख्या

  • while read line; do ... ; done < file : यह एक क्लासिक है while लूप जो इनपुट फ़ाइल की प्रत्येक पंक्ति को पढ़ेगा file और इसे के रूप में सहेजें $line
  • [[ $line =~ ^\* ]] && pat="${line#\*}" : अगर लाइन एक के साथ शुरू होता है *, उसके बाद सबकुछ हटा दें (यही वह है ${line#\*} करता है, अधिक जानकारी के लिए, देखें यहाँ) और इसे के रूप में सहेजें $pat। *|| printf "%s%s\n" "$line" "$pat"; : यदि पिछला आदेश विफल हुआ (इसलिए, रेखा तारांकन से शुरू नहीं होती है), रेखा और वर्तमान मान मुद्रित करें $pat


7
2018-04-25 13:14





मेरे पसंदीदा पायथन के माध्यम से ...

with open('/path/to/the/file') as f:
    counter = False
    for line in f:
        if line.startswith('*') and not counter:
            m = line.strip().lstrip('*')
            counter = True
        elif line.startswith('*') and counter:
            counter = False    
        elif counter:
            if not line.startswith('*'):
                print(line.strip() + m)
        else:
            print(line.strip())  

3
2018-04-25 15:01





देर से आया था। यहाँ एक और है python दृष्टिकोण:

#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
    for lines in f.read().split('*'):
        entries = lines.rstrip().split('\n')
        for i in range(1, len(entries)):
            print entries[i] + entries[0]

3
2018-04-25 21:09