बैश का उपयोग करके कॉलम द्वारा कमांड का स्प्लिट आउटपुट?


87

मैं यह करना चाहता हूँ:

  1. एक कमांड चलाएं
  2. उत्पादन पर कब्जा
  3. एक लाइन का चयन करें
  4. उस पंक्ति के एक कॉलम का चयन करें

एक उदाहरण के रूप में, मान लें कि मैं कमांड नाम को एक से प्राप्त करना चाहता हूं $PID(कृपया ध्यान दें कि यह सिर्फ एक उदाहरण है, मैं सुझाव नहीं दे रहा हूं कि प्रक्रिया आईडी से कमांड नाम प्राप्त करने का यह सबसे आसान तरीका है - मेरी असली समस्या यह है एक और कमांड जिसका आउटपुट प्रारूप मैं नियंत्रित नहीं कर सकता)।

अगर मैं दौड़ता psहूँ तो मुझे मिलता है:


  PID TTY          TIME CMD
11383 pts/1    00:00:00 bash
11771 pts/1    00:00:00 ps

अब मैं करता हूं ps | egrep 11383और मिलता हूं

11383 pts/1    00:00:00 bash

अगला चरण: ps | egrep 11383 | cut -d" " -f 4। आउटपुट है:

<absolutely nothing/>

समस्या यह है कि cutआउटपुट को एकल स्थानों से काटता है, और जैसा psकि तालिका के कुछ समानता रखने के लिए 2 और 3 कॉलम के बीच कुछ रिक्त स्थान जोड़ता है, cutएक खाली स्ट्रिंग चुनता है। बेशक, मैं cut7 वें और 4 वें क्षेत्र का चयन करने के लिए उपयोग कर सकता था , लेकिन मैं कैसे जान सकता हूं, खासकर जब आउटपुट पहले से ही चर और अज्ञात हो।


2
Awk (और 25 और अक्षर) का उपयोग करें।
माइकल फोकरिसिस

जवाबों:


178

एक आसान तरीका trकिसी भी दोहराया क्षेत्र विभाजकों को निचोड़ने के लिए एक पास जोड़ना है:

$ ps | egrep 11383 | tr -s ' ' | cut -d ' ' -f 4

1
मुझे यह पसंद trहै , जैसा दिखता हैawk
फ्लाईबीवायर

3
मैं सहमत होना चाहूंगा, लेकिन यह भी हो सकता है क्योंकि मैंने जागना नहीं सीखा है। :)
खोलना

काम नहीं करेगा यदि आप पीआईडी ​​के साथ एक प्रक्रिया करते हैं जिसमें पीआईडी ​​शामिल है जिसे आप एक सबरिंग के रूप में रुचि रखते हैं।
डेविड ग्रेसन 19

1
और अगर कुछ पीआईडी: एस अंतरिक्ष बाईं ओर गद्देदार होते हैं, तो क्षेत्र के सदस्य बंद हो जाएंगे, जबकि अन्य नहीं हैं।
14

68

मुझे लगता है कि जाग का उपयोग करने का सबसे सरल तरीका है । उदाहरण:

$ echo "11383 pts/1    00:00:00 bash" | awk '{ print $4; }'
bash

4
मूल प्रश्न, ps | awk "\$1==$PID{print\$4}"या (बेहतर) के साथ संगतता के लिए ps | awk -v"PID=$PID" '$1=PID{print$4}'। बेशक, लिनक्स पर आप बस xargs -0n1 </proc/$PID/cmdline | head -n1या तो कर सकते हैं readlink /proc/$PID/exe, लेकिन किसी भी तरह ...
ephemient

है ;में { print $4; }आवश्यक है? इसे हटाने से लिनक्स पर मेरे लिए कोई प्रभाव नहीं पड़ता है, यह उद्देश्य के रूप में उत्सुक है
प्रज्वलित करना

यदि आप प्रिंट स्टेटमेंट को अतीत में जोड़ना जारी रखना चाहते हैं तो @igniteflow यह कमांड के अंत का संकेत नहीं देगा?
23

16

कृपया ध्यान दें कि tr -s ' 'विकल्प किसी एक अग्रणी स्थान को नहीं हटाएगा। यदि आपका कॉलम सही-संरेखित है (जैसा कि pspid के साथ है ) ...

$ ps h -o pid,user -C ssh,sshd | tr -s " "
 1543 root
19645 root
19731 root

तब काटने से उन क्षेत्रों में से कुछ के लिए एक खाली लाइन हो जाएगी यदि यह पहला स्तंभ है:

$ <previous command> | cut -d ' ' -f1

19645
19731

जब तक आप इसे एक स्थान से पहले नहीं रखते हैं, जाहिर है

$ <command> | sed -e "s/.*/ &/" | tr -s " "

अब, पीआईडी ​​नंबर (नाम नहीं) के इस विशेष मामले के लिए, एक फ़ंक्शन है जिसे कहा जाता है pgrep:

$ pgrep ssh


शैल कार्य

हालांकि, सामान्य तौर पर यह अभी भी संक्षिप्त रूप में शेल फ़ंक्शन का उपयोग करना संभव है, क्योंकि readकमांड के बारे में एक साफ बात है :

$ <command> | while read a b; do echo $a; done

पढ़ने के लिए पहला पैरामीटर, aपहले कॉलम का चयन करता है, और यदि अधिक है, तो बाकी सब कुछ डाल दिया जाएगा b। नतीजतन, आपको अपने कॉलम +1 की संख्या से अधिक चर की आवश्यकता नहीं है

इसलिए,

while read a b c d; do echo $c; done

फिर 3 कॉलम का उत्पादन करेगा। जैसा कि मेरी टिप्पणी में संकेत दिया गया है ...

एक पढे हुए रीड को ऐसे वातावरण में निष्पादित किया जाएगा जो कॉलिंग स्क्रिप्ट के लिए चर को पास नहीं करता है।

out=$(ps whatever | { read a b c d; echo $c; })

arr=($(ps whatever | { read a b c d; echo $c $b; }))
echo ${arr[1]}     # will output 'b'`


द अर्रे सॉल्यूशन

तो फिर हम @frayser द्वारा उत्तर के साथ समाप्त होते हैं जो शेल चर IFS का उपयोग करना है जो एक स्थान पर चूक करता है, स्ट्रिंग को एक सरणी में विभाजित करने के लिए। हालांकि यह केवल बैश में काम करता है। डैश और ऐश इसका समर्थन नहीं करते हैं। मेरे पास एक व्यस्त बॉक्स में घटकों में एक स्ट्रिंग को विभाजित करने में वास्तव में कठिन समय है। यह एक एकल घटक (जैसे कि awk का उपयोग करके) प्राप्त करने के लिए पर्याप्त आसान है और फिर आपको हर पैरामीटर के लिए इसे दोहराने की आवश्यकता है। लेकिन फिर आप एक ही लाइन पर बार-बार awk को कॉल करते हैं, या बार-बार एक ही लाइन पर इको के साथ रीड ब्लॉक का उपयोग करते हैं। जो कुशल या सुंदर न हो। तो आप अंत में बंटवारे का उपयोग कर रहे हैं ${name%% *}और इसी तरह। आपको कुछ पायथन कौशलों के लिए तरसता है क्योंकि वास्तव में शेल स्क्रिप्टिंग में बहुत मज़ा नहीं आता है, यदि आप जिन सुविधाओं के आदी हैं, उनमें से आधे या अधिक, चला गए हैं। लेकिन आप मान सकते हैं कि इस तरह के सिस्टम पर भी अजगर स्थापित नहीं किया जाएगा, और यह ;-) नहीं था।


आपको चर में echo "$a"और उसके आसपास उद्धरण का उपयोग करना चाहिए echo "$c"
तिहरा

ऐसा लगता है कि जैसे कि हर पाइप्ड ब्लॉक को अपने ही सबस्क्रिप्शन या प्रोसेस में अंजाम दिया जाता है और आप किसी भी वैरिएबल को एनक्लोजिंग ब्लॉक में नहीं लौटा सकते? हालांकि आप इसे इको करने के बाद इसका आउटपुट प्राप्त कर सकते हैं। var=$(....... | { read a b c d; echo $c; })। यह केवल एक एकल (स्ट्रिंग) के लिए काम करता है, हालांकि बैश में आप इसे एक सरणी में विभाजित कर सकते हैंar=($var)
Xennex81

@tripleee मुझे नहीं लगता कि इस प्रक्रिया के इस स्तर पर एक मुद्दा है। आपको जल्द ही पता चल जाएगा कि आपको इसकी आवश्यकता है या नहीं, और यदि वह किसी बिंदु पर टूटता है, तो यह एक सीखने का सबक है। और फिर आप जानते हैं कि आपको उन दोहरे उद्धरण चिह्नों का उपयोग क्यों करना पड़ा ;-) और फिर यह अब कुछ ऐसा नहीं है जिसे आपने दूसरों से कहते सुना है। आग से साथ खेलना! : डी। : पी।
Xennex81

विस्तृत उत्तर: D
n कंप्यूटर्स

ऐसा न कह पाना मेरे लिए यह एक उत्तर के लिए भी मददगार था।
इवान एक्स

4

प्रयत्न

ps |&
while read -p first second third fourth etc ; do
   if [[ $first == '11383' ]]
   then
       echo got: $fourth
   fi       
done

1
@flybywire - संभवतः इस सरल उदाहरण के लिए ओवरकिल है, लेकिन यह मुहावरा उत्कृष्ट है यदि आपको चयनित डेटा पर अधिक जटिल प्रसंस्करण करने की आवश्यकता है।
जेम्स एंडरसन

इसके अलावा, ध्यान रखें कि इन दिनों डिफ़ॉल्ट स्क्रिप्टिंग शेल आमतौर पर बैश नहीं होता है।
डेविड ने

2

सरणी चर का उपयोग करना

set $(ps | egrep "^11383 "); echo $4

या

A=( $(ps | egrep "^11383 ") ) ; echo ${A[3]}

2

ब्रायनगेज के awk समाधान के समान, यहाँ पर्ल समतुल्य है:

ps | egrep 11383 | perl -lane 'print $F[3]'

-aऑटोसप्लिट मोड को सक्षम करता है, जो @Fकॉलम डेटा के साथ सरणी को पॉप्युलेट करता है । स्पेस-सीमांकित के बजाय यदि आपका डेटा कॉमा-सीमांकित है, तो
उपयोग करें -F,

फ़ील्ड 3 को मुद्रित किया जाता है क्योंकि पर्ल 1 के बजाय 0 से गिनती शुरू करता है


1
आपके पर्ल समाधान के लिए धन्यवाद - ऑटोसप्लिट के बारे में नहीं पता था, और अभी भी लगता है कि पर्ल अन्य टूल को समाप्त करने का उपकरण है;);)
गेरार्ड ओनील

1

सही लाइन प्राप्त करना (लाइन नंबर 6 के लिए उदाहरण) सिर और पूंछ के साथ किया जाता है और सही शब्द (शब्द संख्या 4) को awk के साथ कैप्चर किया जा सकता है:

command|head -n 6|tail -n 1|awk '{print $4}'

बस भविष्य के पाठकों के लिए ध्यान देने वाली बात है कि awk लाइन के अनुसार भी चयन कर सकते हैं: awk NR=6 {print $4}थोड़ा और अधिक कुशल होगा
David Z

1
और उस पाठ्यक्रम से मेरा तात्पर्य awk NR==6 {print $4}* doh *
David Z

1

आपकी आज्ञा

ps | egrep 11383 | cut -d" " -f 4

tr -sरिक्त स्थान को निचोड़ने के लिए एक याद आती है , जैसा कि उसके उत्तर में बताया गया है ।

हालाँकि, आप शायद उपयोग करना चाहते हैं awk, क्योंकि यह इन सभी क्रियाओं को एक ही कमांड में संभालता है:

ps | awk '/11383/ {print $4}'

यह उन पंक्तियों में 4 वें कॉलम को प्रिंट करता है 11383। यदि आप चाहते हैं कि यह 11383पंक्ति की शुरुआत में दिखाई दे, तो आप कह सकते हैं ps | awk '/^11383/ {print $4}'


0

इन सभी greps और सामान को करने के बजाय, मैं आपको आउटपुट स्वरूप बदलने की ps क्षमताओं का उपयोग करने की सलाह दूंगा।

ps -o cmd= -p 12345

आप एक प्रक्रिया की cmmand लाइन को pid ​​के साथ निर्दिष्ट करते हैं और कुछ नहीं।

यह POSIX- अनुरूप है और इस प्रकार इसे पोर्टेबल माना जा सकता है।


1
flybywire वह केवल उदाहरण के रूप में ps का उपयोग कर रहा है, सवाल उससे अधिक सामान्य है।
Ogre Psalm33

0

बैश की setस्थिति आउटपुट में सभी आउटपुट को पार्स करेगी।

उदाहरण के लिए, set $(free -h)कमांड के साथ , echo $7"मेम:" दिखाई देगा


यह विधि केवल तभी उपयोगी होती है जब कमांड में आउटपुट की एक पंक्ति हो। पर्याप्त सामान्य नहीं है।
कोडवर्ड

यह सच नहीं है, सभी आउटपुट लाइनों की परवाह किए बिना स्थितीय मापदंडों में रखे जाते हैं। पूर्व set $(sar -r 1 1); echo "${23}"
dman

मेरा कहना यह था कि जब उत्पादन स्वैच्छिक होता है और कई क्षेत्र होते हैं, तो तर्क की स्थिति निर्धारित करना कठिन है। awkइसके बारे में जाने का सबसे अच्छा तरीका है।
कोडवर्ड

यह सिर्फ एक और उपाय है। हो सकता है कि ओपी इस एकल उपयोग मामले के लिए अजीब भाषा सीखना न चाहे। टैग राज्य करते हैं bashऔर नहीं awk
1717
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.