bash: आउटपुट का n-th कॉलम प्राप्त करने का सबसे छोटा तरीका


166

मान लीजिए कि आपके कार्यदिवस के दौरान आप बार-बार कुछ कमांड से स्तंभित आउटपुट के निम्न रूप को bash (मेरे मामले svn stमें मेरी कार्यशील निर्देशिका में निष्पादित करने से ) में सामना करते हैं :

?       changes.patch
M       app/models/superman.rb
A       app/models/superwoman.rb

आपकी कमांड के आउटपुट के साथ काम करने के लिए - इस मामले में फ़ाइल नाम - कुछ प्रकार के पार्सिंग की आवश्यकता होती है ताकि दूसरे कॉलम को अगले कमांड के इनपुट के रूप में उपयोग किया जा सके।

मैं जो कर रहा हूं वह awkदूसरे कॉलम में प्राप्त करने के लिए उपयोग करना है, उदाहरण के लिए जब मैं सभी फ़ाइलों को निकालना चाहता हूं (ऐसा नहीं है कि यह एक विशिष्ट usecase है :), मैं करूंगा:

svn st | awk '{print $2}' | xargs rm

चूंकि मैं इसे बहुत टाइप करता हूं, इसलिए एक स्वाभाविक सवाल यह है कि क्या इस तरह से बैश में इसे पूरा करने का एक छोटा (इस प्रकार ठंडा) तरीका है?

नोट: मैं जो पूछ रहा हूं वह अनिवार्य रूप से एक शेल कमांड प्रश्न है, हालांकि मेरा ठोस उदाहरण मेरे svn वर्कफ़्लो पर है। यदि आपको लगता है कि वर्कफ़्लो मूर्खतापूर्ण है और एक वैकल्पिक दृष्टिकोण का सुझाव देता है, तो मैं शायद आपको वोट नहीं दूंगा, लेकिन अन्य लोग कर सकते हैं, क्योंकि यहाँ सवाल यह है कि वास्तव में कैसे n-th कॉलम कमांड आउटपुट को bash में प्राप्त किया जा सकता है, कम से कम संभव तरीके से । धन्यवाद :)


1
जब आप एक कमांड का उपयोग करते हैं तो अक्सर आप एक स्क्रिप्ट बनाने में बेहतर होते हैं और इसे अपने रास्ते में डालते हैं। आप बस अपने bashrc में एक समारोह बना सकते हैं यदि आप बेहतर पसंद करते हैं। मैं कॉलम चयन अभिव्यक्ति को कम करने की बात नहीं देखता।
लिंच

1
आप सही हैं, और मैं ऐसा कर सकता हूं। 'बिंदु' सीखने के प्रयोजनों के लिए, बाश में सामान करने के नए तरीकों की खोज है, लेकिन ज्यादातर मज़े के लिए :)
Sv1

1
जब आपके पास ssh-ing कहीं नहीं है तो आपके पास आपका .bashrc नहीं है, इसलिए इसके बिना अपना रास्ता जानना उपयोगी है।
कोस

जवाबों:


125

आप cutदूसरे फ़ील्ड को एक्सेस करने के लिए उपयोग कर सकते हैं :

cut -f2

संपादित करें: क्षमा करें, महसूस नहीं किया गया कि SVN अपने आउटपुट में टैब का उपयोग नहीं करता है, इसलिए यह थोड़ा बेकार है। आप cutआउटपुट के लिए दर्जी कर सकते हैं लेकिन यह थोड़ा नाजुक है - कुछ ऐसाcut -c 10- ऐसा काम करेगा, लेकिन सटीक मूल्य आपके सेटअप पर निर्भर करेगा।

एक अन्य विकल्प कुछ इस प्रकार है: sed 's/.\s\+//'


1
आउटपुट के cut -f2साथ उपयोग करने का प्रयास करें svn st। आप देखेंगे कि यह काम नहीं करता है।
लिंच

मैंने मान लिया कि असली svn stअपने आउटपुट में टैब का उपयोग करेगा। कुछ परीक्षण के बाद ऐसा लगता है कि यह मामला नहीं है। अरे नहीं।
बजे

21
-dइसे काम करने की अनुमति देने के लिए एक उपयुक्त परिसीमन पास करना।
योग

6
@Yogh ने जो कहा, उस पर विस्तार करने के लिए, सीमांकक के रूप में रिक्त स्थान के लिए, ऐसा लगेगा cut -d" " -f2
adamyonk

डब्ल्यू / ओ awk पर stdout उपयोग xargs: svn सेंट | xargs | cut -d "" -f2
vr286

106

के रूप में एक ही बात को पूरा करने के लिए:

svn st | awk '{print $2}' | xargs rm

केवल बैश का उपयोग करके आप उपयोग कर सकते हैं:

svn st | while read a b; do rm "$b"; done

दी, यह कम नहीं है, लेकिन यह थोड़ा अधिक कुशल है और यह आपके फाइलनाम में व्हाट्सएप को सही ढंग से संभालता है।


क्या है aऔर b, उन्हें कैसे मिलता है?
तिमो

1
@ टिमो aपहले कॉलम का bप्रतिनिधित्व करता है और शेष कॉलम का प्रतिनिधित्व करता है। यदि आप दूसरे कॉलम को प्रिंट करना चाहते हैं, read a b c;तो echoइसके बजाय उपयोग करें और फिर उपयोग करें rm। मैंने इसका उपयोग आईडी की प्रक्रिया का एक गुच्छा प्राप्त करने के लिए किया था जो एक grep पैटर्न का पालन करता था, इसलिए मैं उन सभी को बाधित कर सकता था।
मैट क्लींसमिथ

36

मैंने खुद को उसी स्थिति में पाया और इन उपनामों को अपनी .profileफ़ाइल में जोड़ लिया :

alias c1="awk '{print \$1}'"
alias c2="awk '{print \$2}'"
alias c3="awk '{print \$3}'"
alias c4="awk '{print \$4}'"
alias c5="awk '{print \$5}'"
alias c6="awk '{print \$6}'"
alias c7="awk '{print \$7}'"
alias c8="awk '{print \$8}'"
alias c9="awk '{print \$9}'"

जो मुझे इस तरह की चीजें लिखने की अनुमति देता है:

svn st | c2 | xargs rm

15
बैश फ़ंक्शन आमतौर पर अधिक उपयोगी होते हैं। मैंने ऐसा किया: function c() { awk "{print \$$1}" } फिर आप कर सकते हैं: svn st | c 2 | xargs rm
एसेन

8
लेकिन फिर मुझे एक अतिरिक्त जगह टाइप करने की आवश्यकता है। यह बहुत थक गया है :)
StackedCroched

16

Zsh की कोशिश करो। यह प्रत्यय उपनाम का समर्थन करता है, ताकि आप अपने .zshrc में X को परिभाषित कर सकें

alias -g X="| cut -d' ' -f2"

तो आप कर सकते हैं:

cat file X

आप इसे एक कदम आगे ले जा सकते हैं और इसे nth कॉलम के लिए परिभाषित कर सकते हैं:

alias -g X2="| cut -d' ' -f2"
alias -g X1="| cut -d' ' -f1"
alias -g X3="| cut -d' ' -f3"

जो फ़ाइल "फ़ाइल" के nth कॉलम को आउटपुट करेगा। आप इसे grep आउटपुट या कम आउटपुट के लिए भी कर सकते हैं। यह बहुत आसान है और चिड़ियाघर की एक हत्यारा सुविधा है।

आप एक कदम आगे जा सकते हैं और डी को परिभाषित कर सकते हैं:

alias -g D="|xargs rm"

अब आप टाइप कर सकते हैं:

cat file X1 D

फ़ाइल "फ़ाइल" के पहले कॉलम में उल्लिखित सभी फ़ाइलों को हटाने के लिए।

अगर आप बैश जानते हैं, तो कुछ नए फीचर्स को छोड़कर, zsh ज्यादा बदलाव वाला नहीं है।

एचटीएच क्रिस


आह, मुझे लगता है कि आपने अपना जवाब अपडेट कर दिया है, जबकि मैं ऊपर अपनी टिप्पणी टाइप कर रहा था :) क्या आप किसी तरह गतिशील रूप से निर्दिष्ट कर सकते हैं कि किस कॉलम को प्राप्त करना है, या क्या मुझे अपने .zshrc में n-लाइनों की आवश्यकता होगी (यह महत्वपूर्ण नहीं है, बस जिज्ञासु)
Sv1

मैंने अपनी पोस्ट को आगे संपादित किया है और फ़ाइलों को हटाने के लिए एक प्रत्यय "D" को परिभाषित किया है। जहाँ तक मुझे पता है कि आपको प्रत्येक प्रत्यय के लिए एक पंक्ति जोड़नी होगी।
क्रिस

या इसे X कमांड का पहला पैरामीटर बनाते हैं। इसमें से किसी को भी zsh या उपनाम की आवश्यकता नहीं है, सिवाय शायद अजीबोगरीब विचार के लिए एक अन्य में एक पाइप लगाने के लिए।
ट्रिपल

1
मुझे समझ नहीं आ रहा है कि आप सभी को यह cutविकल्प क्यों पसंद आ रहा है। यह बस के उत्पादन का उपयोग कर मेरी मशीन पर काम नहीं करता है svn stsvn st | cut -d' ' -f2बस कोशिश करें कि क्या हो सकता है।
लिंच

@ Sv1 आप उपनामों को परिभाषित करने के लिए एक लूप लिख सकते हैं, क्योंकि उपनाम केवल एक आदेश है।
बहाव

8

क्योंकि आप लिपियों से अपरिचित लगते हैं, यहाँ एक उदाहरण है।

#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=$1
shift
awk -v col="$col" '{print $col}' "${@--}"

यदि आप इसे सहेजते हैं ~/bin/xऔर यह सुनिश्चित ~/binकरते PATHहैं कि आपके (अब ऐसा कुछ है जिसे आप कर सकते हैं और अपने में रखना चाहिए .bashrc) आपके पास आमतौर पर कॉलम n निकालने के लिए सबसे कम संभव कमांड है; x n।

यदि गैर-सांख्यिक तर्क या गलत संख्या के तर्क, आदि के साथ मंगाया जाता है, तो स्क्रिप्ट को उचित त्रुटि जाँच और जमानत करनी चाहिए; लेकिन इस नंगे-हड्डियों के आवश्यक संस्करण का विस्तार इकाई 102 में होगा।

हो सकता है कि आप एक अलग स्तंभ परिसीमन की अनुमति देने के लिए स्क्रिप्ट का विस्तार करना चाहेंगे। व्हॉट्सएप पर खेतों में डिफ़ॉल्ट पार्स इनपुट द्वारा जागें; एक अलग सीमांकक उपयोग करने के लिए, का उपयोग करें -F ':'जहां :नई सीमांकक है। स्क्रिप्ट के विकल्प के रूप में इसे लागू करने से यह थोड़ा लंबा हो जाता है, इसलिए मैं इसे पाठक के लिए एक अभ्यास के रूप में छोड़ रहा हूं।


प्रयोग

एक फ़ाइल दी file:

1 2 3
4 5 6

आप इसे या तो स्टड के माध्यम से पारित कर सकते हैं ( कुछ अधिक उपयोगी के लिए एक प्लेसहोल्डर के रूप में बेकारcat का उपयोग करके );

$ cat file | sh script.sh 2
2
5

या इसे स्क्रिप्ट के तर्क के रूप में प्रदान करें:

$ sh script.sh 2 file
2
5

यहां, sh script.shयह मानते हुए कि स्क्रिप्ट को script.shवर्तमान निर्देशिका में सहेजा गया है; यदि आप इसे अपने कहीं और अधिक उपयोगी नाम के साथ सहेजते हैं PATHऔर इसे निष्पादन योग्य चिह्नित करते हैं, जैसा कि ऊपर दिए गए निर्देशों में है, तो स्पष्ट रूप से इसके बजाय (और नहीं sh) उपयोगी नाम का उपयोग करें ।


अच्छा विचार है, लेकिन मेरे लिए काफी काम नहीं है जैसा कि श या बैश पर है। यह काम करता है: #! / Bin / bash col = $ 1 शिफ्ट awk "{print \ $$ col}"
mgk

इस देर से टिप्पणी के लिए धन्यवाद। अपने फिक्स के साथ अपडेट किया गया।
ट्रिपल

1
बेहतरawk -v col=$col ...
फेडोरक्वी 'SO

@fedorqui आपकी प्रतिक्रिया के लिए धन्यवाद, यहाँ और कहीं! उत्तर अपडेट किया गया। अब यह थोड़ा लंबा है अगर आप चाहते हैं कि आपके पास सबसे छोटी स्क्रिप्ट हो, तो मूल संस्करण के लिए संशोधन इतिहास देखें ।
त्रिवेणी

1
@fedorqui एक गुच्छा धन्यवाद! cat
हिस्टेरिकल

5

ऐसा लगता है कि आपके पास पहले से ही एक समाधान है। चीजों को आसान बनाने के लिए, क्यों न केवल अपनी कमांड को बैश स्क्रिप्ट (संक्षिप्त नाम के साथ) में डालें और हर बार उस 'लंबी' कमांड को टाइप करने के बजाय केवल चलाएं?


यह सिर्फ इतना है कि मेरी राय में 'शांत' नहीं है। क्यों? अच्छी तरह से मैं अपने .bashrc को विभिन्न शॉर्टकट के साथ बाढ़ नहीं करना चाहता हूं जो ऐसा करते हैं और अनिवार्य रूप से मेटा-शेल लिख रहे हैं। इसके रूप में यह बहुत सुंदर है। ऐसा कहने के बाद, आपका सुझाव बुरा नहीं है।
Sv1

2
.bashrc? आप इसे गैर-बैश संबंधित सामान के साथ क्यों अव्यवस्थित करेंगे। मैं जो कुछ भी करता हूं, मैं कमांड के प्रत्येक 'सेट' के लिए अलग-अलग स्क्रिप्ट लिखता हूं और उन सभी को एक ~/scriptsनिर्देशिका में रखता हूं । फिर पूरे ~/scriptsको मेरे साथ जोड़ दें PATHताकि मैं उन्हें जरूरत पड़ने पर नाम से पुकार सकूं।
तारेक फड़

4
फिर इसे अपने .bashrc में न डालें। ~ / बिन में एक स्क्रिप्ट बनाएं और सुनिश्चित करें कि यह आपके पेट पर है।
7

2

यदि आप स्तंभ को मैन्युअल रूप से चुनने के साथ ठीक हैं, तो आप पिक का उपयोग करके बहुत तेज़ हो सकते हैं :

svn st | pick | xargs rm

बस 2 कॉलम के किसी भी सेल पर जाएं, दबाएं cऔर फिर हिट करेंenter


मैंने "पिक" टूल आज़माया था जिसे आपने संदर्भित किया था, और मुझे यह बहुत पसंद है। यह बहुत सारी स्थितियों के लिए बहुत अच्छा है जहाँ मैं चयनित कॉलम प्रिंट करना चाहता हूँ, लेकिन केवल वांछित कॉलम प्राप्त करने के लिए "awk '{$ 3}" प्रिंट नहीं करना चाहता। दुर्भाग्य से नाम एक अलग "पिक" टूल के साथ संघर्ष करता है जो अधिक लोकप्रिय प्रतीत होता है - इसे "एप्ट इंस्टॉल पिक" के साथ स्थापित किया जा सकता है। इसलिए मैंने अपने टूल का नाम बदलकर अपने सिस्टम पर "पिक" कर दिया, और इसे इस्तेमाल करते रहने का इरादा किया। एक संदर्भ पोस्ट करने के लिए धन्यवाद।
विलियम

1

ध्यान दें, उस फ़ाइल पथ में svn सेंट आउटपुट के दूसरे कॉलम में नहीं होना चाहिए। उदाहरण के लिए यदि आप फ़ाइल को संशोधित करते हैं, और इसे संशोधित करते हैं, तो यह 3 कॉलम होगा।

संभावित आउटपुट उदाहरण देखें:

svn help st

उदाहरण आउटपुट:

 M     wc/bar.c
A  +   wc/qax.c

मैं पहले 8 वर्णों को काटने का सुझाव देता हूं:

svn st | cut -c8- | while read FILE; do echo whatever with "$FILE"; done

यदि आप 100% सुनिश्चित होना चाहते हैं, और उदाहरण के लिए अंत में सफेद स्थान के साथ फैंसी फ़ाइलनाम से निपटना चाहते हैं, तो आपको XX आउटपुट को पार्स करने की आवश्यकता है:

svn st --xml | grep -o 'path=".*"' | sed 's/^path="//; s/"$//'

बेशक आप grep / sed के बजाय कुछ वास्तविक XML पार्सर का उपयोग करना चाह सकते हैं।

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