मैं शेल कमांड का उपयोग करके किसी फ़ाइल की पहली एन लाइन्स और लास्ट लाइन को कैसे हटा सकता हूँ?


31

मेरे पास एक फ़ाइल है, Element_queryजिसमें एक क्वेरी का परिणाम है:

SQL> select count (*) from element;

[Output of the query which I want to keep in my file]

SQL> spool off;

मैं शेल कमांड का उपयोग करके पहली पंक्ति और अंतिम पंक्ति को हटाना चाहता हूं।


2
आप शायद SQL * प्लस के अंदर इसे ठीक कर रहे हैं; फ़ाइल जेनरेट करने के बजाय और फिर उस सामान को ट्रिम करने की कोशिश करें जिसे आप नहीं चाहते हैं, आप बस SQL ​​* प्लस को बता सकते हैं कि शुरू करने के लिए उस सामान को उत्पन्न न करें। डॉक्स .oracle.com / cd / A84870_01 / doc / sqlplus.816 / a75664 / ch44.htm पर एक दृष्टिकोण "एक फ्लैट फ़ाइल बनाना" अनुभाग में वर्णित है ; एक अन्य दृष्टिकोण stackoverflow.com/q/2299375/978917 पर वर्णित है ।
बरबाद

जवाबों:


48

GNU का उपयोग करना sed:

sed -i '1d;$d' Element_query

यह काम किस प्रकार करता है :

  • -iविकल्प फ़ाइल को ही संपादित करें। आप उस विकल्प को भी हटा सकते हैं और यदि चाहें तो आउटपुट को एक नई फ़ाइल या किसी अन्य कमांड पर पुनर्निर्देशित कर सकते हैं।
  • 1dपहली पंक्ति को हटाता है ( 1केवल पहली पंक्ति पर कार्य करने के लिए,d इसे हटाने के लिए)
  • $dअंतिम पंक्ति को हटाता है ( $केवल अंतिम पंक्ति पर कार्य करने के लिए, dइसे हटाने के लिए)

आगे बढ़ते हुए :

  • आप किसी श्रेणी को हटा भी सकते हैं। उदाहरण के लिए, 1,5dपहले 5 लाइनों को हटा देगा।
  • आप हर उस रेखा को भी हटा सकते हैं जो इसके साथ शुरू होती है SQL> कथन का उपयोग करके/^SQL> /d
  • आप हर रिक्त पंक्ति को हटा सकते हैं /^$/d
  • अंत में, आप किसी भी स्टेटमेंट को सेमी-कॉलन ( statement1;statement2;satement3;...) के साथ अलग करके या कमांड लाइन पर अलग से निर्दिष्ट करके जोड़ सकते हैं ( -e 'statement1' -e 'statement 2' ...)

यदि इसकी तीसरी लाइन को हटाना है ... तो मुझे 1d के स्थान पर 3 डी का उपयोग करना होगा? यदि इसकी तीसरी पंक्ति को हटाने के लिए पिछले से ... तो कमांड क्या होगा?
पमिपमुई

शेल कमांड का उपयोग करके अंतिम से तीसरी पंक्ति को कैसे हटाएं?
पमिपमुई

@ नैनीता आप एक सीमा निर्दिष्ट कर सकते हैं ( 1,3dपहले तीन पंक्तियों को हटा देंगे) लेकिन यह अंत के लिए थोड़ा अधिक कठिन है। आप जो चाहते हैं उसके आधार पर, आप इसका उपयोग करना बेहतर हो सकते हैं: उन sed -i '/^SQL> /d' Element_queryपंक्तियों को हटाने के लिए जो SQL> किसी भी मामले में शुरू नहीं होती हैं जहां यह फ़ाइल में है।
यूजर 43791

@Nainita - मनमाने ढंग से पूंछ गिनती के लिए मेरा जवाब यहाँ देखें - यह फ़ाइल के अंत के रूप में गिनती लाइनों को अलग करने के लिए दो समाधान प्रदान करता है । एक sedएक-लाइनर है - जो एक फ़ाइल के सिर और पूंछ से मनमाने ढंग से लाइन काउंट्स को अलग करने के लिए काम करेगा , हालांकि बेहतर है, जब तक इनपुट एक नियमित फ़ाइल है, बस दो headप्रक्रियाओं में एकल इनपुट को समूहीकृत करना है - यह है ऐसा करने का सबसे तेज़ तरीका।
मिकसेर

मैंने sed -i '1d' table-backup.sqlsql पाठ फ़ाइल की पहली पंक्ति को हटा दिया
डेविड थॉमस

8

सिर; सिर

{   head -n[num] >/dev/null
    head -n[num]
}  <infile >outfile

उपरोक्त के साथ आप आउटपुट w / पहला headकमांड के सिर को छीनने के लिए लाइनों की पहली संख्या निर्दिष्ट कर सकते हैं , और outfileदूसरी के साथ लिखने के लिए लाइनों की संख्या । यह आम तौर पर इस तेजी से भी करेगा sed- खासकर जब इनपुट बड़ा है - दो चालान की आवश्यकता के बावजूद। कहाँ sedनिश्चित रूप से करना चाहिए , हालांकि पसंद किया जा, ऐसा होता है कि में है <infileहै नहीं एक नियमित रूप से, lseekable क्योंकि यह आम तौर पर होगा - फ़ाइल नहीं है कि मामले में इरादा किया था लेकिन के रूप में काम sedएक एकल, पटकथा प्रक्रिया में सभी उत्पादन संशोधनों संभाल कर सकते हैं।

जीएनयू के साथ head आप दूसरे कमांड के -लिए भी नकारात्मक रूप का उपयोग कर सकते हैं [num]। किस स्थिति में निम्नलिखित कमांड इनपुट से पहली और आखिरी लाइनें छीन लेगी:

{   head -n1 >/dev/null
    head -n-1
}  <infile >outfile

या एक POSIX के साथ sed:

उदाहरण के लिए, मैं 20 लाइनों का एक इनपुट पढ़ रहा था और मैं पहले 3 और आखिरी को छीनना चाहता था। 7. अगर मैंने ऐसा करने का संकल्प लिया / sed , मैं इसे टेल बफर के साथ करूँगा। मैं पहले तीन और सात को दस की कुल स्ट्रिप गिनती के लिए एक साथ जोड़ूंगा और फिर करूँगा:

seq 20 | sed -ne:n -e '3d;N;1,10bn' -eP\;D

यह एक उदाहरण है जो इनपुट से पहले 3 और अंतिम 7 लाइनों को स्ट्रिप्स करता है। विचार यह है कि आप स्टैक पर पैटर्न स्पेस में इनपुट की पूंछ से पट्टी करने के लिए जितनी चाहें उतनी पंक्तियों को बफर कर सकते हैं, लेकिन Pइनमें से खींची गई प्रत्येक पंक्ति के लिए केवल सबसे पहले रिंट करें।

  • तर्ज पर 1,10 sed P कुछ भी नहीं होता है क्योंकि उनमें से प्रत्येक के लिए यह एक रिंच लूप में पैटर्न स्पेस लाइन-बाय-लाइन में इनपुट स्टैकिंग है b
  • 3 वीं पंक्ति के सभी पर sed स्टैक को dहटा दिया गया है - और इसलिए पहली 3 पंक्तियों को एक झपट्टा में आउटपुट से छीन लिया गया है।
  • जब इनपुट sedकी $अंतिम पंक्ति तक पहुँचता है और एक्सट में खींचने का प्रयास करता है तो Nयह ईओएफ से टकराता है और पूरी तरह से प्रसंस्करण बंद कर देता है। लेकिन उस समय पैटर्न स्पेस में सभी लाइनें होती हैं 14,20- जिनमें से कोई भी अभी तक Printed नहीं हुई है, और कभी नहीं होती है।
  • हर दूसरी पंक्ति में sed Pकेवल \nपैटर्न स्पेस में पहली होने वाली इवलाइन तक संकेत मिलता है, और Dजो कुछ भी रहता है उसके साथ एक नया चक्र शुरू करने से पहले ईलेट्स - या इनपुट की अगली 6 लाइनें। 7 वीं पंक्ति को फिर से Nनए चक्र में अतिरिक्त कमांड के साथ स्टैक में जोड़ा जाता है।

और इसलिए , केवल seqआउटपुट (जो 20 क्रमिक रूप से क्रमांकित रेखाएं हैं) , sedकेवल प्रिंट:

4
5
6
7
8
9
10
11
12
13

यह समस्याग्रस्त हो जाता है जब आप इनपुट की पूंछ से पट्टी करने की इच्छा वाली लाइनों की संख्या बड़ी होती है - क्योंकि sedइसका प्रदर्शन सीधे इसके पैटर्न अंतरिक्ष के आकार के लिए आनुपातिक है। फिर भी, हालांकि, यह कई मामलों में एक व्यवहार्य समाधान है - और POSIX sedबस्ट करने से पहले कम से कम 4kb को संभालने के लिए एक पैटर्न स्पेस को निर्दिष्ट करता है।


1
ग्नू tailविस्तारित tail -n+<num>वाक्यविन्यास अर्थ का भी समर्थन करता है जिसका अर्थ है "लाइन से शुरू होना <num>"
UloPe

4

मैं यह जवाब नहीं देने वाला हूं कि कई लाइनों को कैसे हटाया जाए। मैं इस तरह से समस्या पर हमला करने जा रहा हूँ:

grep -v '#SQL>' Element_query >outfile

लाइनों की गिनती के बजाय, यह संकेतों को पहचानकर SQL कमांड को समाप्त करता है। यह समाधान तब SQL सत्र के अन्य आउटपुट फ़ाइलों के लिए सामान्य से अधिक कमांड के साथ सामान्यीकृत किया जा सकता है।


मुझें यह पसंद है। मैं एसक्यूएल के बारे में बहुत कुछ नहीं जानता - लेकिन क्या इसके उत्पादन लाइनों के प्रमुख पर होने वाले संकेतों का कोई मौका नहीं है अन्यथा?
मिकसेर

4

ed'मानक पाठ संपादक' है और उन सिस्टमों पर उपलब्ध होना चाहिए जिनके पास GNU नहीं है sed। यह मूल रूप से एक पाठ संपादक के रूप में तैयार किया गया था, लेकिन यह पटकथा के अनुकूल है।

printf '%s\n' 1d '$d' w q | ed Element_query

1dफ़ाइल की पहली पंक्ति को हटाता है, $d(उद्धृत किया गया है ताकि शेल को नहीं लगता कि यह एक चर है) अंतिम पंक्ति को हटा देता है, wफ़ाइल लिखता है और qक्विट करता है edprintfयहाँ आदेशों को प्रारूपित करने के लिए उपयोग किया जाता है ed- प्रत्येक के लिए एक नई पंक्ति का पालन करना आवश्यक है; इसे पूरा करने के अन्य तरीके हैं।


3

फ़ाइल से लीडिंग और ट्रेलिंग लाइन (एस) को हटाने के कई तरीके हैं।

आप इसका उपयोग कर सकते हैं awkक्योंकि यह पैटर्न मिलान और लाइन काउंटिंग दोनों को संभालता है,

#you need to know length to skip last line, assume we have 100 lines
awk 'NR>1 && NR<100 {print $0};' < inputfile
#or
awk '/SQL/ {next}; {print $0;};' < inputfile |awk 'NR>1&& NR<10 {print $0};'

आप grep -vउन लाइनों को बाहर करने के लिए उपयोग कर सकते हैं जिन्हें आप पैटर्न से नहीं चाहते हैं, और आप -Eविकल्प का उपयोग करके कई पैटर्न से मिलान कर सकते हैं ,

grep -v -E "SQL>" < inputfile > outputfile

आप लाइनों की विशिष्ट गणनाओं का उपयोग कर सकते हैं, headऔरtail

lines=$((`wc -l < inputfile`-2)) #how many lines in file, less 2
head -n-1 < inputfile | head -n$lines > outputfile
#or
tail -n+2 < inputfile | head -n$lines > outputfile

आप vi/vimपहली और अंतिम पंक्ति का उपयोग कर सकते हैं और हटा सकते हैं ,

vi inputfile
:1
dd
:$
dd
:w! outputfile
:x

आप एक पर्ल स्क्रिप्ट का उपयोग कर सकते हैं, पहली पंक्ति को छोड़ सकते हैं, प्रत्येक पंक्ति को बचा सकते हैं, अगली पंक्ति मिलने पर प्रिंट कर सकते हैं,

#left as exercise for the reader :-)

1
के लिए headहै कि आप वास्तव में पाइप की जरूरत नहीं है, और, वास्तव में यह बेहतर सब पर इसका इस्तेमाल करने की है, तो आप इसके साथ प्राप्त कर सकते हैं नहीं है। जब आप करते हैं head | head- जबकि दो प्रक्रियाएँ समवर्ती रूप से चल सकती हैं, तो वे दोनों व्यावहारिक रूप से समान रूप से एक ही डेटा के सभी प्रसंस्करण कर रहे हैं। यदि आप इसके बजाय { head >dump; head >save; } <inकेवल ऑफसेट द्वारा छोड़ते हैं - पहला 10 लाइनों को >dumpपढ़ता है और दूसरा अगली 10 पंक्तियों को पढ़ता है >save
मिकसर्व

3

SQL कमांड को काटकर आपको बेहतर सेवा दी जाएगी । आप इसे दो तरीकों से कर सकते हैं:

  1. यदि आपको पूरा यकीन है कि अनुक्रम " SQL>" आउटपुट में कहीं और नहीं होता है,

    grep -v -F 'SQL> ' < infile > outfile
  2. यदि आप निश्चित नहीं हैं,

    grep -v '^SQL> .*;$' < infile > outfile

दूसरा संस्करण धीमा लेकिन अधिक सटीक है: यह "एसक्यूएल" के साथ शुरू होने वाली लाइनों और सेमीकोलन में समाप्त होने वाली रेखाओं की उपेक्षा करेगा, जो उन लाइनों का वर्णन करते हैं जो आप समाप्त करना चाहते हैं।

हालांकि, यह बेहतर होगा कि उस अतिरिक्त आउटपुट को फाइल में न डालें। अधिकांश SQL सिस्टम के पास ऐसा करने का कोई तरीका है। मैं ओरेकल के साथ बहुत ज्यादा बातचीत नहीं कर रहा हूं, लेकिन शायद यह जवाब मददगार हो सकता है।


3

आप एक सीमा के बीच लाइनों का चयन कर सकते हैं awk(यह आपको पता है कि कितनी लाइनें हैं):

awk 'NR>1 && NR < 3' file

या पर्ल में:

perl -ne 'print if $.>1 && $.<3' file

यदि आपको नहीं पता कि कितनी लाइनें हैं, तो आप इसका उपयोग करके मक्खी पर गणना कर सकते हैं grep(ध्यान दें कि यह खाली लाइनों की गणना नहीं करेगा, grep -c '' fileउन्हें भी गिनने के लिए उपयोग करें):

awk -vm="$(grep -c . file2.txt)" 'NR>1 && NR<m' file2.txt

3

इस समाधान का प्रयास करें:

tail -n +2 name_of_file | head -n-1

अनुकूलन

आप आसानी से n पहले लाइनों को बदलने को हटाने के लिए यह अनुकूलित कर सकते हैं +2की tail;
या बदलते पिछले n लाइनों को हटाने के लिए -1की head


यह समाधान गलत है क्योंकि यह पहली पंक्ति को प्रिंट करता है।
xhienne

1
@xhienne क्षमा करें, यह एक गलती थी। मैंने "पूंछ" के पैरामीटर के रूप में 2 के बजाय 1 लिखा। अब यह काम करता है, धन्यवाद! :)
गबरर

1

का उपयोग कर awk:

< inputfile awk 'NR>1 {print r}; {r=$0}' > outputfile
  • < inputfile: की सामग्री पुनर्निर्देश inputfileकरने awkकेstdin
  • > outputfile: की सामग्री पुनर्निर्देश awkके stdoutलिएoutputfile
  • NR>1: निम्नलिखित कार्यों को केवल तभी निष्पादित करता है जब रिकॉर्ड किए जा रहे रिकॉर्ड की संख्या 1 से अधिक हो
  • {print r}: चर की सामग्री को प्रिंट करता है r
  • {r=$0}: चर को संसाधित किए जा रहे रिकॉर्ड की सामग्री को असाइन करता है r

इसलिए awkस्क्रिप्ट के पहले निष्पादन पर , क्रियाओं के पहले ब्लॉक को निष्पादित नहीं किया जाता है, जबकि कार्यों के दूसरे ब्लॉक को निष्पादित किया जाता है और रिकॉर्ड की सामग्री को चर को सौंपा जाता है r; दूसरे निष्पादन में, क्रियाओं के पहले ब्लॉक को निष्पादित किया जाता है, और चर की सामग्री rमुद्रित होती है (इसलिए पिछला रिकॉर्ड मुद्रित होता है); इसमें प्रत्येक संसाधित लाइनों को प्रिंट करने का प्रभाव है, लेकिन पहले वाला और आखिरी वाला।


आप पहली पंक्ति को बाहर नहीं कर रहे हैं। NR == 2 पर, आप इनपुट की पहली लाइन प्रिंट करते हैं, जो इसमें स्टोर की जाती है r
xhienne
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.