केवल एक पाठ फ़ाइल में पहला कॉलम और अंतिम कॉलम दिखाने के लिए शेल कमांड का उपयोग कैसे करें?


30

मुझे एक पाठ फ़ाइल में केवल पहले कॉलम और अंतिम कॉलम को दिखाने के लिए sed कमांड का उपयोग करने का तरीका जानने के लिए कुछ सहायता की आवश्यकता है। यहाँ कॉलम 1 के लिए मेरे पास अभी तक क्या है:

cat logfile | sed 's/\|/ /'|awk '{print $1}'

आखिरी कॉलम दिखाने के लिए मेरा यह प्रयास कितना अच्छा था:

cat logfile | sed 's/\|/ /'|awk '{print $1}{print $8}'

हालाँकि यह पहला कॉलम और अंतिम कॉलम लेता है और उन्हें एक सूची में एक साथ मिला देता है। क्या पहला कॉलम और आखिरी कॉलम स्पष्ट रूप से sed और awk कमांड से प्रिंट करने का एक तरीका है?

नमूना इनपुट:

foo|dog|cat|mouse|lion|ox|tiger|bar

5
कृपया कुछ नमूना इनपुट प्रदान करें।
जसोनव्रीयन

जवाबों:


51

लगभग वहाँ। बस दोनों स्तंभ संदर्भों को एक दूसरे के बगल में रखें।

cat logfile | sed 's/|/ /' | awk '{print $1, $8}'

यह भी ध्यान दें कि आपको catयहाँ ज़रूरत नहीं है।

sed 's/|/ /' logfile | awk '{print $1, $8}'

यह भी ध्यान दें awkकि आप बता सकते हैं कि कॉलम विभाजक |रिक्त स्थान के बजाय है, इसलिए आपको इसकी आवश्यकता नहीं है sed

awk -F '|' '{print $1, $8}' logfile

के अनुसार सुझाव द्वारा कालेब , यदि आप एक समाधान है कि अभी भी अंतिम फ़ील्ड आउटपुट, भले ही वास्तव में आठ नहीं हैं चाहते हैं, आप उपयोग कर सकते हैं $NF

awk -F '|' '{print $1, $NF}' logfile

इसके अलावा, यदि आप आउटपुट को |विभाजकों को बनाए रखना चाहते हैं, तो किसी स्थान का उपयोग करने के बजाय, आप आउटपुट फ़ील्ड विभाजकों को निर्दिष्ट कर सकते हैं। दुर्भाग्य से, यह केवल -Fध्वज का उपयोग करने की तुलना में थोड़ा अधिक अनाड़ी है , लेकिन यहां तीन दृष्टिकोण हैं।

  • आप इनपुट और आउटपुट फ़ील्ड विभाजकों awkको BEGIN ब्लॉक में स्वयं असाइन कर सकते हैं ।

    awk 'BEGIN {FS = OFS = "|"} {print $1, $8}' logfile
  • awkकमांड लाइन से -vध्वज के माध्यम से कॉल करते समय आप इन चर को असाइन कर सकते हैं ।

    awk -v 'FS=|' -v 'OFS=|' '{print $1, $8}' logfile
  • या केवल:

    awk -F '|' '{print $1 "|" $8}' logfile

4
अच्छी नौकरी टूटने से यह समस्या कैसे सरल हो सकती है। आप एक |स्ट्रिंग जोड़ने के लिए डिफ़ॉल्ट स्थान के बजाय आउटपुट विभाजक के रूप में उपयोग करने के बारे में एक नोट जोड़ सकते हैं । इसके अलावा आप अंतिम कॉलम को पाने के लिए $NFहार्ड कोडिंग के बजाय उपयोग करने के लिए समझा सकते हैं $8
कालेब

12

अभी पिछले करने के लिए पहले से की जगह |एक साथ |(या अंतरिक्ष यदि आप चाहें):

sed 's/|.*|/|/'

ध्यान दें कि कोई नहीं है, हालांकि sedकार्यान्वयन जहां |खास है (जब तक विस्तारित नियमित अभिव्यक्ति के माध्यम से सक्षम नहीं हैं -Eया -rमें कुछ कार्यान्वयन), \|खुद को जीएनयू जैसे कुछ में खास है sed। तो तुम चाहिए नहीं बच |अगर आप मैच के लिए यह इरादा |चरित्र।

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

sed 's/|\(.*|\)\{0,1\}/ /'

(यह .*|हिस्सा वैकल्पिक है) या:

sed 's/|.*|/ /;s/|/ /'

या:

sed 's/\([^|]*\).*|/\1 /'

यदि आप इनपुट में फ़ील्ड की संख्या की परवाह किए बिना पहला और आठवां फ़ील्ड चाहते हैं, तो यह सिर्फ है:

cut -d'|' -f1,8


(उन सभी (इनपुट रूपों वैध पाठ संभालने विशेष रूप से किसी भी POSIX शिकायत उपयोगिता के साथ काम करेंगे, sedअच्छे लगेंगे आम तौर पर काम नहीं करता है, तो इनपुट बाइट या बाइट्स कि उदाहरण के लिए की तरह वर्तमान स्थान में मान्य वर्ण फार्म नहीं है के दृश्यों है printf 'unix|St\351phane|Chazelas\n' | sed 's/|.*|/|/'में एक UTF-8 स्थान))।


11

आप awkवैसे भी उपयोग कर रहे हैं :

awk '{ print $1, $NF }' file

2
क्या आपको इनपुट फ़ील्ड विभाजक को निर्दिष्ट करने की आवश्यकता नहीं होगी (क्योंकि इस मामले में ऐसा लगता है |कि वह जगह है) -F\|या समान? इसके अलावा अगर वह आउटपुट के लिए समान सीमांकक का उपयोग करना चाहता है, तो क्या होगा?
कालेब

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

1
ध्यान दें कि इनपुट मानता है कि कम से कम 2 फ़ील्ड शामिल हैं।
स्टीफन चेज़लस

@ स्टीफनचेज़ेलस ओपी ने स्पष्ट रूप से कोड में कहा है कि इसके आठ क्षेत्र हैं, हमेशा।
michaelb958 -

3
@ michaelb958 मुझे लगता है कि "स्पष्ट रूप से" मामले पर
काबू पा रहा है

4

यदि आप अपने आप को अजीब और सेड-लेस पाते हैं, तो आप कोरुटिल्स के साथ एक ही चीज हासिल कर सकते हैं:

paste <(           cut -d'|' -f1  file) \ 
      <(rev file | cut -d'|' -f1 | rev)

cutजब आप बस पहले कॉलम में रुचि रखते हैं, या अगर डिलेमीटर तय हो गए हैं (यानी रिक्त स्थान की एक परिवर्तनीय संख्या नहीं है) तो क्लीनर और अधिक कॉम्पैक्ट है।
श्रीधर सरनोबत

2

ऐसा लगता है कि आप पाठ के पहले और अंतिम क्षेत्रों को प्राप्त करने की कोशिश कर रहे हैं जो कि सीमांकित हैं |

मुझे लगा कि आपकी लॉग फ़ाइल में नीचे जैसा पाठ है,

foo|dog|cat|mouse|lion|ox|tiger|bar
bar|dog|cat|mouse|lion|ox|tiger|foo

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

foo bar
bar foo

यदि हाँ, तो यहाँ आपके लिए कमांड आती है

GNU sed के माध्यम से,

sed -r 's~^([^|]*).*\|(.*)$~\1 \2~' file

उदाहरण:

$ echo 'foo|dog|cat|mouse|lion|ox|tiger|bar' | sed -r 's~^([^|]*).*\|(.*)$~\1 \2~'
foo bar

स्तंभ एक पाइप द्वारा सीमांकित नहीं हैं | लेकिन वे कॉलम में हैं, मैं sed का उपयोग करने में दिलचस्पी रखता हूं लेकिन आपके आदेश में आपके जैसे किए गए awk कमांड का उपयोग नहीं कर रहा है: sed -r 's ~ ^ ([^ |] *) *। * \ | (*। *) $ ~ \ 1 \ 2 ~ 'फ़ाइल
user70573

"स्तंभों को एक पाइप द्वारा सीमांकित नहीं किया गया है। लेकिन वे स्तंभों में हैं", आपका मतलब है कि कॉलम रिक्त स्थान द्वारा अलग किए गए हैं?
अविनाश राज

एक नमूना इनपुट और एक आउटपुट बेहतर होगा।
अविनाश राज

1

आपको शायद इसके साथ करना चाहिए sed- मैं वैसे भी - लेकिन, बस कारण किसी ने भी अभी तक यह नहीं लिखा है:

while IFS=\| read col1 cols
do  printf %10s%-s\\n "$col1 |" " ${cols##*|}"
done <<\INPUT
foo|dog|cat|mouse|lion|ox|tiger|bar
INPUT

आउटपुट

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