मैं कमांड के आउटपुट से उद्धृत स्ट्रिंग्स की सामग्री कैसे निकालूं?


26

मेरे पास आउटपुट है VBoxManage list vmsजिससे यह दिखता है:

"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}   
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}  

मैं नाम हड़पने के लिए की जरूरत है archऔर arch2और उन्हें एक चर में सहेजें।

जवाबों:


34

Grep + sed का उपयोग करना

यह उन 2 तारों की सामग्री को पार्स करेगा:

$ grep -o '".*"' somefile | sed 's/"//g'
arch
arch2

उपरोक्त पैटर्न से मेल खाते स्ट्रिंग के लिए दिखता है ".*"। यह डबल कोट्स के भीतर होने वाली किसी भी चीज़ से मेल खाएगा। तो grepइन प्रकार के मूल्यों को वापस करेगा:

"arch"
"arch2"

पाइप sedइन स्ट्रिंग्स से किसी भी दोहरे उद्धरणों को छीन लेगा, जो आपके द्वारा खोजे जा रहे तार दे रहा है। अंकन एक खोज करने और दोहरे उद्धरण चिह्नों के सभी घटनाओं पर प्रतिस्थापित करने के लिए sed 's/"//g'निर्देश sedदे रहा है, उन्हें कुछ भी नहीं के साथ प्रतिस्थापित करते हुए s/"//g,। कमांड s/find/replace/gवहाँ क्या चल रहा है, और gखोज करने के लिए अनुगामी इसे पूरे स्ट्रिंग पर विश्व स्तर पर करने के लिए कहता है जो इसे दिया गया है।

सिर्फ sed का उपयोग करना

आप sedशुरुआत के दोहरे उद्धरण को काट देने के लिए भी उपयोग कर सकते हैं, उनके बीच में क्या है, और शेष बोली + सब कुछ के बाद काट लें:

$ sed 's/^"\(.*\)".*/\1/' a
arch
arch2

अन्य विधियाँ

$ grep -o '".*"' somefile | tr -d '"'
arch
arch2

trवर्णों को हटाने के लिए कमांड का उपयोग किया जा सकता है। इस मामले में यह दोहरे उद्धरण चिह्नों को हटा रहा है।

$ grep -oP '(?<=").*(?=")' somefile
arch
arch2

grepपीसीआरई सुविधा का उपयोग करके आप किसी भी सबस्ट्रिंग की तलाश कर सकते हैं जो एक दोहरे उद्धरण के साथ शुरू होता है या एक दोहरे उद्धरण के साथ समाप्त होता है और केवल प्रतिस्थापन की रिपोर्ट करता है।


1
tr -d \"उद्धरण हटाने का एक और तरीका है। ( trआम तौर पर वर्णों के एक सेट का दूसरे में अनुवाद करता है; -dयह बताता है कि इसके बजाय उन्हें हटा दें।)
डेल्टब

1
एसएलएम - यदि आप एक जोड़ने के /address/लिए sedपसंद sed '/^"\(arch[^"]*\)/s//\1/करते हैं तो आप केवल उस स्ट्रिंग वाले लाइनों पर काम करेंगे।
माइकस

1
@mikeserv - सच है, यह सुनिश्चित नहीं था कि आर्क अपने आउटपुट में कितना सुसंगत होने वाला था। लेकिन अगर ऐसा है, तो वह भी काम करेगा।
स्लम

1
अच्छी बात कोई संकेत नहीं है कि सुसंगत होगा। माफ़ कीजिये।
माइकस

2
मुझे बस एहसास हुआ कि आपके sedवास्तव s/^"\([^"]*\)".*/\1/में सिर्फ ऐसे मामले में होना चाहिए जब लाइन पर केवल दो दोहरे उद्धरण हों।
मिकसर्व

19

इसके लिए एक और काम है cut:

VBoxManage list vms | cut -d \" -f2

3
बहुत साफ़! यह कैसे काम करता है: cutप्रत्येक रेखा को परिसीमन के रूप में उद्धरण चिह्न का उपयोग करके फ़ील्ड में विभाजित करता है, फिर फ़ील्ड 2 को आउटपुट करता है: फ़ील्ड 1 पहले उद्धरण से पहले खाली स्ट्रिंग है, फ़ील्ड 2 उद्धरणों के बीच वांछित स्ट्रिंग है, और फ़ील्ड 3 शेष भाग है लाइन।
डेल्टब

7

साथ sedआप कर सकते हैं:

var=$(VBoxManage list vms | sed 's/^"\([^"]*\).*/\1/')

स्पष्टीकरण:

  • s/.../.../ - मैच और बदलें
  • ^- लाइन की शुरुआत में मैच
  • \(...\) - यह एक बैक रेफरेंस है, हम बाद में यहां से जो मिलान किया गया है उसका संदर्भ ले सकते हैं \1
  • [^"]*- किसी भी अनुक्रम से मेल खाता है जिसमें एक नहीं है "(यानी अगले तक ")
  • .* - बाकी लाइन से मैच करें
  • \1 - पीछे संदर्भ के साथ बदलें

या साथ awk:

var=$(VBoxManage list vms | awk -F\" '{ print $2 }')

ध्यान दें कि आधुनिक गोले में आप एक सामान्य चर के बजाय एक सरणी का उपयोग कर सकते हैं। में bashआप कर सकते हैं:

IFS=$'\n'; set -f
array=( $(VBoxManage list vms | awk -F\" '{ print $2 }') )
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"

जब आप चर का उपयोग करने के लिए आते हैं तो यह आसान हो सकता है।


क्या आप मेरे लिए उस सेड कमांड को तोड़ देंगे?
हर्रिज कावन

5

बैश का उपयोग करते हुए, मैं लिखूंगा:

while read vm value; do
    case $vm in
        '"arch"') arch=$value ;;
        '"arch2"') arch2=$value ;;
    esac
done < <( VBoxManage list vms )
echo $arch
echo $arch2

5

और --perl-regexpविकल्प के साथ grep oneliner के माध्यम से एक ,

VBoxManage list vms | grep -oP '(?<=^\")[^"]*'

स्पष्टीकरण:

(?<=^\")[^"]*-> यहां एक लुकबाइंड का उपयोग किया जाता है। यह किसी भी वर्ण से मेल खाता है, लेकिन "शून्य या अधिक बार नहीं (एक बार दोहरे उद्धरण मिल जाने पर, यह मेल खाना बंद कर देता है) जो दोहरे उद्धरण के बाद (केवल पंक्ति जो दोहरे उद्धरणों से शुरू होती है)।

एक और बदसूरत हैक के माध्यम से sed,

$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
arch
arch2

0

चूंकि रेगेक्स में लालची और गैर-लालची मोड हैं, यदि आपके पास एक ही पंक्ति में कई लक्ष्य हैं, तो यह आपकी इच्छा के अनुसार नहीं निकलेगा। रेखा:

"tom" is a cat, and "jerry" is a mouse. 

लक्ष्य:

tom
jerry

कमांड (लालची मोड):

grep -oP '".*"' name

कमांड (गैर-लालची मोड):

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