लिनक्स में किसी फ़ाइल के अंतिम कॉलम को कैसे हटाएं


25

मैं एक txt फ़ाइल के अंतिम कॉलम को हटाना चाहता हूं, जबकि मुझे नहीं पता कि कॉलम नंबर क्या है। मैं ये कैसे करूं?

उदाहरण:

इनपुट:

1223 1234 1323 ... 2222 123
1233 1234 1233 ... 3444 125
0000 5553 3455 ... 2334 222

और मैं चाहता हूं कि मेरा आउटपुट:

1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

ऐसा करने के कई तरीके हैं..प्लीज एक उदाहरण और इसमें से आपके अपेक्षित आउटपुट को जोड़ दें ..
heemayl

@ हेमायल ओके मैंने किया
ज़रा

धन्यवाद .. क्या कॉलम टैब अलग हो गया या स्पेस अलग हो गया?
हेमायल

@heemayl स्पेस डिमिलिमिनेटर है
zara

जवाबों:


43

के साथ awk:

awk 'NF{NF-=1};1' <in >out

या:

awk 'NF{NF--};1' <in >out

या:

awk 'NF{--NF};1' <in >out

हालांकि यह वूडू जैसा दिखता है, यह काम करता है। इन awk कमांड में से प्रत्येक के तीन भाग हैं।

पहला है NF, जो दूसरे भाग के लिए एक पूर्व शर्त है। NFएक चर है जिसमें एक पंक्ति में फ़ील्ड्स की संख्या होती है। AWK में, यदि वे 0 या खाली स्ट्रिंग नहीं हैं तो चीजें सही हैं ""। इसलिए, दूसरा भाग (जहां NFकमी है) केवल तब होता है जब NF0 न हो।

दूसरे भाग (या तो NF-=1 NF--या --NF) बस से घटाने पर है NFचर। यह अंतिम फ़ील्ड को प्रिंट होने से रोकता है, क्योंकि जब आप फ़ील्ड बदलते हैं (इस मामले में अंतिम फ़ील्ड को हटाते हैं), awkफिर से निर्माण करें $0, डिफ़ॉल्ट रूप से अंतरिक्ष द्वारा अलग किए गए सभी फ़ील्ड को फिर से बनाएँ। $0अब अंतिम फ़ील्ड शामिल नहीं है।

अंतिम भाग है 1। यह जादुई नहीं है, इसका उपयोग केवल अभिव्यक्ति के रूप में किया जाता है true। यदि कोई awkअभिव्यक्ति बिना किसी संबद्ध क्रिया के सत्य का मूल्यांकन करती है, तो awkडिफ़ॉल्ट क्रिया है print $0


@ जोजो: आह, धन्यवाद, भूल गए --। एक नोट, वर्तमान में, आपको ;1पोसिक्स के अनुपालन की आवश्यकता है ।
congonglm

मेरी प्रारंभिक वृत्ति पाश के लिए उपयोग की जाएगी, लेकिन यह अधिक संक्षिप्त और चतुर है।
सर्गी कोलोडाज़हनी

5
यह ध्यान देने योग्य है कि यदि आप एक गैर-डिफ़ॉल्ट सीमांकक का उपयोग कर रहे हैं, तो आपको कुछ परिवर्तन करने की आवश्यकता होगी। मान ,लेना आपका परिसीमन है:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
श्री लामा

1
एनएफ घटने का प्रभाव पोसिक्स द्वारा अपरिभाषित व्यवहार है - आप अलग-अलग आउटपुट प्राप्त करेंगे जिसके आधार पर आप चल रहे हैं। कुछ awk पिछले फ़ील्ड को हटा देंगे जैसा आप चाहते हैं, कुछ बिल्कुल भी नहीं करेंगे, और अन्य एक सिंटैक्स त्रुटि या कुछ और रिपोर्ट कर सकते हैं।
एड मॉर्टन

16

grepपीसीआरई के साथ प्रयोग :

$ grep -Po '.*(?=\s+[^\s]+$)' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

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

$ sed -r 's/(.*)\s+[^\s]+$/\1/' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

1
@ramin ज़रूर..क्या आप इसे एक नया प्रश्न पूछें (यह साइट इस तरह काम करती है) :)
heemayl

@ramin क्या यह आपको किसी भी समय प्रतिबंध या कोई चेतावनी देता है?
हेम्यल

यह कहता है कि यह मानक प्रश्न से बाहर है!
ज़रा

@ramin Ok..let मुझे एक व्यवस्थापक से संपर्क करें, हो सकता है कि वे आपकी इसमें मदद कर सकें..क्या आपने अपने प्रश्न के बारे में किसी पुराने क्यूए की जांच की? इसकी संभावना है कि प्रश्न पहले से ही पूछा गया है और उत्तर दिया गया है
heemayl

3
सुपर बुनियादी सवाल मत पूछें जैसे " मैं लिनक्स में एक फ़ाइल का नाम कैसे बदल सकता हूं "। गूगल का प्रयोग करें।
क्रिस्टोफर हैमरस्ट्रॉम

11

पर्ल का उपयोग करना:

perl -lane '$,=" ";pop(@F);print(@F)' in

rev+ का उपयोग कर cut:

rev in | cut -d ' ' -f 2- | rev

5

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

sed -r 's/\s+\S+$//' input.txt

आमतौर पर, यह OSD में BSD sed के साथ-साथ GNU sed के साथ काम करता है:

sed 's/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//' input.txt

1

यदि सीमांकक हमेशा एक सिंगल चार होता है (इसलिए दो या अधिक लगातार सीमांकक खाली फ़ील्ड को नामित करते हैं), तो आप headअपनी इनपुट फ़ाइल से सिर्फ पहली पंक्ति दे सकते हैं , सीमांकक ( nडेलिमिटर का मतलब खेतों की संख्या है n+1) cutको गिनें, फिर 1सेंट फ़ील्ड से प्रिंट करने के लिए उपयोग करें। अप करने के लिए nवें क्षेत्र (दूसरा पिछले एक करने के लिए), टैब-सीमांकित इनपुट के साथ उदाहरण के लिए:

n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l)
cut -f1-$n infile > outfile

या एक सीएसवी फ़ाइल के साथ जैसे :

n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l)
cut -d, -f1-$n infile > outfile

यदि मेरे पास समय है तो मैं कुछ बेंचमार्क चलाऊंगा लेकिन मुझे लगता है कि इस इनपुट के साथ यह समाधान अन्य समाधानों की तुलना में तेज होना चाहिए जो रेगेक्स का उपयोग करते हैं क्योंकि यह कोई नहीं पाने के लिए पहली पंक्ति में न्यूनतम प्रसंस्करण करता है। फ़ील्ड्स का उपयोग करता है और फिर cutइस काम के लिए अनुकूलित किया जाता है।


1

आप इनमें से किसी का भी उपयोग कर सकते हैं:

sed 's/[[:space:]]*[^[:space:]]*$//' file

awk '{sub(/[[:space:]]*[^[:space:]]*$/,"")}1' file

0

विम का उपयोग करना:

Vim में फ़ाइल खोलें

vim <filename> 

पहली पंक्ति पर जाएं, यदि कर्सर को कहीं और रखा गया हो तो बस।

gg

"Q" नाम का एक मैक्रो बनाएं qq, जो वर्तमान लाइन के $पीछे जाता है, फिर अंतिम स्थान पर वापस जाता है F(कैपिटल एफ, इसके बाद शाब्दिक स्पेस) फिर लाइन की समाप्ति के माध्यम से वर्तमान स्थिति से हटकर Dअगली पंक्ति में नीचे जाता है jऔर साथ मैक्रो रिकॉर्डिंग बंद करो q

qq$F Djq

अब हम @qप्रत्येक लाइन के लिए अपने मैक्रो को दोहरा सकते हैं ।
हम @@अंतिम मैक्रो या और भी आसान दोहराने के लिए दबा सकते हैं :

99@q

99 बार मैक्रो दोहराने के लिए।
नोट: संख्या को बिल्कुल लाइनों से मेल नहीं खाना चाहिए।


0

ऐसे लोगों के लिए जिनके पास एक समान समस्या है, लेकिन विभिन्न क्षेत्र विभाजकों के साथ यह awkविधि क्षेत्र विभाजक को सही ढंग से संरक्षित करेगी:

$ cat file 
foo.bar.baz
baz.bar.foo
$ awk -F'.' 'sub(FS $NF,x)' file
foo.bar
baz.bar
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.