टेक्स्ट फाइल की तर्ज पर विशेष शब्दों को कैसे हटाया जाए?


13

मेरी पाठ फ़ाइल इस तरह दिखती है:

Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341

अब मैं Liquid penetration 95% mass (m)केवल मान प्राप्त करने के लिए अपनी लाइनों से हटाना चाहता हूं। मैं इसे कैसे करूं?


3
बसgrep -o '[^[:space:]]\+$' file
अविनाश राज

@AvinashRaj: इस समय के लिए, इस समाधान हो जाता है 'पोटीन पदक' :)
pa4080

2
@ pa4080 कम से कम मेरे द्वारा परीक्षण किए गए इनपुट (10M लाइनों) के लिए, अविनाश राज के सामान्य दृष्टिकोण को PCRE का उपयोग करके तेजी से परिमाण का क्रम बनाया जा सकता है। (मैं पुष्टि कर सकता था कि इंजन, पैटर्न नहीं, जिम्मेदार है, क्योंकि GNU grep या \S+$तो स्वीकार करता है ।) इसलिए इस तरह का समाधान स्वाभाविक रूप से धीमा नहीं है। लेकिन मैं अभी भी इसे α stillsнι method की विधि के करीब नहीं पा सकता हूं , जिसने आपका बेंचमार्क भी जीत लिया-E-Pcut
एलियाह कगन

जवाबों:


22

यदि केवल एक =संकेत है, तो आप =इस तरह से पहले और सहित सब कुछ हटा सकते हैं :

$ sed -r 's/.* = (.*)/\1/' file
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341

यदि आप मूल फ़ाइल को बदलना चाहते हैं, तो -iपरीक्षण के बाद विकल्प का उपयोग करें :

sed -ri 's/.* = (.*)/\1/' file

टिप्पणियाँ

  • -rERE का उपयोग करें ताकि हमें बचना न पड़े (और)
  • s/old/newके oldसाथ बदलेंnew
  • .* किसी भी वर्ण की कोई भी संख्या
  • (things)thingsबाद \1में \2, इत्यादि के साथ पीछे हटने के लिए बचाएं

धन्यवाद यह काम किया। मैंने मौजूदा फ़ाइल को अधिलेखित करने के लिए इस कमांड का उपयोग किया है: sed -i -r 's /.*= (। *) / \ 1 /' time.txt। क्या आप बता सकते हैं कि यह कैसे काम करता है?
OE

पिछड़ेपन से क्यों नहीं बचा? s/^.*= //समान रूप से अच्छी तरह से काम करेगा, क्योंकि सही मूल्य लाइन के अंत में है।
jpaugh

@jpaugh आंशिक रूप से, क्योंकि मेरे उत्तर को बदलने में बहुत देर हो चुकी है, जो पहले पोस्ट किया गया था - दूसरों ने पहले ही आपके द्वारा बताए गए समाधान और इस मामले के लिए अन्य अधिक कुशल तरीके दिए हैं :) लेकिन शायद यह दिखाना कि कैसे उपयोग करना है \1आदि का उन लोगों के लिए कुछ मूल्य है जो खोज करते समय इस प्रश्न पर उतरें, कि किसके पास इतनी सरल समस्या नहीं है
Zanna

@Zanna यह अधिक सामान्य है, कम से कम।
jpaugh

21

यह एक नौकरी है awk; मानों को अंतिम फ़ील्ड में ही मानें (आपके उदाहरण के अनुसार):

awk '{print $NF}' file.txt
  • NFएक awkचर है, एक रिकॉर्ड (लाइन) में फ़ील्ड्स की संख्या तक फैलता है, इसलिए $NF( $सामने में नोट करें ) में अंतिम फ़ील्ड का मान होता है।

उदाहरण:

% cat temp.txt 
Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341

% awk '{print $NF}' temp.txt
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341

13

मैंने यहां सूचीबद्ध विभिन्न समाधानों की तुलना करने का निर्णय लिया। इस प्रयोजन के लिए मैंने ओपी द्वारा प्रदान की गई सामग्री के आधार पर एक बड़ी फ़ाइल बनाई है:

  1. मैंने एक साधारण फाइल बनाई, जिसका नाम है input.file:

    $ cat input.file
    Liquid penetration 95% mass (m) = 0.000205348
    Liquid penetration 95% mass (m) = 0.000265725
    Liquid penetration 95% mass (m) = 0.000322823
    Liquid penetration 95% mass (m) = 0.000376445
    Liquid penetration 95% mass (m) = 0.000425341
    
  2. तब मैंने इस पाश को अंजाम दिया:

    for i in {1..100}; do cat input.file | tee -a input.file; done
    
  3. टर्मिनल विंडो को ब्लॉक कर दिया गया था। मैंने killall teeदूसरे टर्मिनल से निष्पादित किया। तब मैंने कमांड द्वारा फ़ाइल की सामग्री की जांच की: less input.fileऔर cat input.file। यह अच्छा लग रहा था, अंतिम पंक्ति को छोड़कर। इसलिए मैं अंतिम पंक्ति हटा दिया और एक बैकअप प्रतिलिपि बनाई: cp input.file{,.copy}(क्योंकि आदेशों उपयोग की inplace विकल्प)।

  4. फाइल में लाइनों की अंतिम गिनती input.fileहै 2 192 473 । मुझे वह नंबर कमांड से मिला wc:

    $ cat input.file | wc -l
    2192473
    

यहाँ तुलना का परिणाम है:

  • grep -o '[^[:space:]]\+$'

    $ समय grep -o '[^ [: space:]] \ + $' input.file> output.file
    
    वास्तविक 0m58.539s
    उपयोगकर्ता 0m58.416s
    sys 0m0.108s
    
  • sed -ri 's/.* = (.*)/\1/'

    $ समय sed -ri का / .* = (। *) / \ 1 / 'input.file
    
    असली 0m26.936s
    उपयोगकर्ता 0m22.836s
    sys 0m4.092s
    

    वैकल्पिक रूप से यदि हम आउटपुट को एक नई फाइल पर पुनर्निर्देशित करते हैं तो कमांड अधिक तेज है:

    $ time sed -r 's /.* = (। *) / \ 1 /' input.file> output.file
    
    असली 0m19.734s
    उपयोगकर्ता 0m19.672s
    sys 0m0.056s
    
  • gawk '{gsub(".*= ", "");print}'

    $ समय gawk '{gsub ("*।
    
    असली 0m5.644s
    उपयोगकर्ता 0m5.568s
    sys 0m0.072s
    
  • rev | cut -d' ' -f1 | rev

    $ समय Rev इनपुट.फाइल | cut -d '' -f1 | Rev> output.file
    
    वास्तविक 0m3.703s
    उपयोगकर्ता 0m2.108s
    sys 0m4.916s
    
  • grep -oP '.*= \K.*'

    $ समय grep -oP '। * = \ K. *' input.file> output.file
    
    असली 0m3.328s
    उपयोगकर्ता 0m3.252s
    sys 0m0.072s
    
  • sed 's/.*= //' (क्रमशः -iविकल्प कमांड को कुछ बार धीमा बनाता है)

    $ time sed 's /.*= //' input.file> output.file
    
    असली 0m3.310s
    उपयोगकर्ता 0m3.212s
    sys 0m0.092s
    
  • perl -pe 's/.*= //' ( -iविकल्प यहाँ उत्पादकता में बड़ा अंतर पैदा नहीं करता है)

    $ समय perl -i.bak -pe 's /.*= //' input.file
    
    असली 0m3.187
    उपयोगकर्ता 0m3.128s
    sys 0m0.056s
    
    $ समय perl -pe 's /.*= //' input.file> output.file
    
    असली 0m3.138s
    उपयोगकर्ता 0m3.036s
    sys 0m0.100s
    
  • awk '{print $NF}'

    $ समय awk '{$ $ NF}' input.file> output.file
    
    वास्तविक 0m1.251s
    उपयोगकर्ता 0m1.164s
    sys 0m0.084s
    
  • cut -c 35-

    $ समय में कटौती -c 35- input.file> output.file
    
    वास्तविक 0m0.352s
    उपयोगकर्ता 0m0.284s
    sys 0m0.064s
    
  • cut -d= -f2

    $ समय कट -d = -f2 input.file> output.file
    
    असली 0m0.328s
    उपयोगकर्ता 0m0.260s
    sys 0m0.064s
    

विचार का स्रोत।


2
इसलिए मेरा cut -d= -f2समाधान जीत गया। haha
αhasнιη

क्या आप इस बारे में अधिक जानकारी दे सकते हैं कि आपने यह फाइल कैसे बनाई? इसके अलावा, wc -lआउटपुट तीन नंबर कैसे करता है ? जब कोई अन्य विकल्प पारित नहीं होता है, तो -lविकल्प को सब कुछ दबा देना चाहिए लेकिन लाइन की गिनती।
एलियाह कगन

@ एलियाकगन, किया। मैंने जवाब अपडेट कर दिया है।
पा ०४० 24०

आह, मैं देखता हूं - रिक्त स्थान अंकों के समूह विभाजक थे। ( wcवास्तव में उन स्थानों को प्रदर्शित किया था ? क्या स्थानीय सेटिंग्स हैं जिसके लिए वह ऐसा करेगा?) अपडेट के लिए धन्यवाद!
एलियाह कगन

@ एलियाकगन: अंत में मैंने आपके सवालों को wcएक और बार पढ़ा । मुझे नहीं पता कि मेरी बुद्धि आज कहां थी, लेकिन मैं वास्तव में उन्हें समझ नहीं पाया। तो वास्तव में रिक्त स्थान अंकों के समूह विभाजक थे , और wcउन्हें नहीं जोड़ता है :)
pa4080

12

के साथ grepऔर -Pहोने के लिए PCRE(एक पी erl- सी ompatible आर egular xpression के रूप में पैटर्न की व्याख्या ) और -oअकेले मिलान पैटर्न मुद्रित करने के लिए। \Kमिलान किया हिस्सा ही पहले आने पर ध्यान नहीं देगा सूचित करें।

$ grep -oP '.*= \K.*' infile
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341

या आप cutइसके बजाय कमांड का उपयोग कर सकते हैं ।

cut -d= -f2 infile

2
चलाने के अलावा में परीक्षण सभी तरीकों का सबसे तेजी से pa4080 के बेंचमार्क , इस जवाब में विधि भी स्पष्ट विजेता था एक छोटे बेंचमार्क मैं भाग गया है कि परीक्षण किया कम तरीकों लेकिन एक बड़ा इनपुट फ़ाइल का इस्तेमाल किया। यह मेरे द्वारा पसंद किए जाने वाले तरीके (और मेरा जवाब मुख्य रूप से है) के तेज संस्करण की तुलना में दस गुना अधिक अच्छी तरह से तेज था। cut
एलिया कागन

11

चूंकि लाइन उपसर्ग में हमेशा समान लंबाई (34 अक्षर) होती है, जिसका आप उपयोग कर सकते हैं cut:

cut -c 35- < input.txt > output.txt

6

इसके साथ फ़ाइल की सामग्री को उल्टा करें rev, आउटपुट cutको सीमांकक के रूप में अंतरिक्ष में और 1 को लक्ष्य क्षेत्र के रूप में पाइप करें , फिर मूल संख्या प्राप्त करने के लिए इसे फिर से रिवर्स करें:

$ rev your_file | cut -d' ' -f1 | rev
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341

5

यह सरल, संक्षिप्त, और लिखना, समझना और जांचना आसान है, और मुझे व्यक्तिगत रूप से यह पसंद है:

grep -oE '\S+$' file

grepउबंटू में , जब -Eया के साथ आह्वान किया जाता है, तो व्हाट्सएप चरित्र का अर्थ करने के -Pलिए शॉर्टहैंड लेता है (व्यवहार में आमतौर पर एक स्थान या टैब) और ऐसा कुछ भी नहीं होने का मतलब है। क्वांटिफायर और एंड-ऑफ-लाइन एंकर का उपयोग करते हुए , पैटर्न एक पंक्ति के अंत में एक या अधिक गैर-रिक्तता से मेल खाता है । आप इसके बजाय उपयोग कर सकते हैं ; इस मामले में अर्थ समान है लेकिन एक अलग नियमित अभिव्यक्ति इंजन का उपयोग किया जाता है, इसलिए उनके पास अलग-अलग प्रदर्शन विशेषताएं हो सकती हैं\s\S+$\S+$-P-E

यह अविनाश राज के टिप्पणी समाधान के बराबर है (बस एक आसान, अधिक कॉम्पैक्ट वाक्य रचना के साथ):

grep -o '[^[:space:]]\+$' file

यदि संख्या के बाद व्हॉट्सएप हो सकता है तो ये दृष्टिकोण काम नहीं करेंगे । उन्हें संशोधित किया जा सकता है इसलिए वे ऐसा करते हैं, लेकिन मुझे इसमें जाने का कोई मतलब नहीं है। यद्यपि यह कभी-कभी अधिक मामलों के तहत काम करने के लिए एक समाधान को सामान्य बनाने के लिए निर्देशात्मक है, लेकिन ऐसा करना व्यावहारिक नहीं है क्योंकि लोग अक्सर ऐसा मानते हैं, क्योंकि किसी के पास आमतौर पर यह जानने का कोई तरीका नहीं होता है कि समस्या के कई अलग-अलग तरीकों में से किसके लिए अंततः आवश्यकता हो सकती है। सामान्य किया जाए।


प्रदर्शन कभी-कभी एक महत्वपूर्ण विचार होता है। यह प्रश्न निर्धारित नहीं करता है कि इनपुट बहुत बड़ा है, और यह संभावना है कि यहां पोस्ट की गई प्रत्येक विधि काफी तेज़ है। हालाँकि, यदि मामले में गति वांछित है, तो दस मिलियन लाइन इनपुट फ़ाइल पर एक छोटा बेंचमार्क है:

$ perl -e 'print((<>) x 2000000)' file > bigfile
$ du -sh bigfile
439M    bigfile
$ wc -l bigfile
10000000 bigfile
$ TIMEFORMAT=%R
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
819.565
$ time grep -oE '\S+$' bigfile > bigfile.out
816.910
$ time grep -oP '\S+$' bigfile > bigfile.out
67.465
$ time cut -d= -f2 bigfile > bigfile.out
3.902
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
815.183
$ time grep -oE '\S+$' bigfile > bigfile.out
824.546
$ time grep -oP '\S+$' bigfile > bigfile.out
68.692
$ time cut -d= -f2 bigfile > bigfile.out
4.135

मैंने दो बार इसे चलाया जब मामले ने आदेश दिया (जैसा कि यह कभी-कभी I / O-भारी कार्यों के लिए होता है) और क्योंकि मेरे पास एक मशीन उपलब्ध नहीं थी जो पृष्ठभूमि में अन्य सामान नहीं कर रही थी जो परिणामों को तिरछा कर सकती थी। उन परिणामों से मैं निम्नलिखित का निष्कर्ष निकालता हूं, कम से कम अनंतिम रूप से और मेरे द्वारा उपयोग किए गए आकार की इनपुट फ़ाइलों के लिए:

  • वाह! पासिंग -P( PCRE का उपयोग करने के बजाय) -G(डिफ़ॉल्ट जब कोई बोली निर्दिष्ट नहीं है) या परिमाण के एक क्रम से अधिक तेज़ -Eबना दिया grepजाता है। इसलिए बड़ी फ़ाइलों के लिए, इस कमांड का उपयोग करना बेहतर हो सकता है, जैसा कि ऊपर दिखाया गया है:

    grep -oP '\S+$' file
  • वाह!! cutमें विधि αғsнιη का जवाब , , यहां तक कि मेरे रास्ते से तेजी से संस्करण की तुलना में तेज परिमाण के एक आदेश खत्म हो गया है! यह Pa4080 के बेंचमार्क में भी विजेता था , जिसने इससे अधिक तरीकों को कवर किया, लेकिन छोटे इनपुट के साथ - और इसीलिए मैंने इसे, अन्य सभी तरीकों में से, अपने टेस्ट में शामिल करने के लिए चुना। यदि प्रदर्शन महत्वपूर्ण है या फाइलें बड़ी हैं, तो मुझे लगता है कि αнsнι method की विधि का उपयोग किया जाना चाहिए।cut -d= -f2 filecut

    यह एक अनुस्मारक के रूप में भी कार्य करता है कि सरल cutऔर pasteउपयोगिताओं को भुलाया नहीं जाना चाहिए , और लागू होने पर शायद पसंद किया जाना चाहिए, हालांकि इस तरह के अधिक परिष्कृत उपकरण हैं grepजिन्हें अक्सर पहली पंक्ति के समाधान के रूप में पेश किया जाता है (और यह कि मैं व्यक्तिगत रूप से अधिक आदी हूं। का उपयोग करते हुए)।


4

perl- रों पैटर्न ubstitute /.*= /रिक्त स्ट्रिंग के साथ //:

perl -pe 's/.*= //' input.file > output.file
perl -i.bak -pe 's/.*= //' input.file
  • से perl --help:

    -e program        one line of program (several -e's allowed, omit programfile)
    -p                assume loop like -n but print line also, like sed
    -i[extension]     edit <> files in place (makes backup if extension supplied)
    

sed - खाली स्ट्रिंग के साथ पैटर्न का विकल्प:

sed 's/.*= //' input.file > output.file

या (लेकिन ऊपर से धीमा) :

sed -i.bak 's/.*= //' input.file
  • मैं इस दृष्टिकोण का उल्लेख करता हूं, क्योंकि यह ज़ाना के उत्तर की तुलना में कुछ गुना तेज है ।

gawk- ".*= "खाली स्ट्रिंग के साथ पैटर्न का विकल्प "":

gawk '{gsub(".*= ", "");print}' input.file > output.file
  • से man gawk:

    gsub(r, s [, t]) For each substring matching the regular expression r in the string t,
                     substitute the string s, and return the number of substitutions. 
                     If t is not supplied, use $0...
    
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.