2016-12-14 4 views
7

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

तो, मैं इस कोशिश कर रहा है:

#!/bin/bash 

f=$'\n\tShare1 Disk\n\tShare2 Disk\n\tPrnt1 Printer' 
regex=$'\n\t(.+?)\\s+Disk' 
if [[ $f =~ $regex ]] 
then 
    for match in "${BASH_REMATCH[@]}" 
    do 
     echo "New match: $match" 
    done 
else 
    echo "No matches" 
fi 

परिणाम:

New match: 
    Share1 Disk 
    Share2 Disk 
New match: Share1 Disk 
    Share2 

उम्मीद परिणाम होता

New match: Share1 
New match: Share2 

मुझे लगता है कि क्योंकि काम नहीं करता है मेरा .+? लालची से मेल खाता है। तो मैंने देखा कि यह बैश रेगेक्स के साथ कैसे पूरा किया जा सकता है। लेकिन हर कोई पेर्ल रेगेक्स के साथ grep का उपयोग करने का सुझाव देता है।

लेकिन निश्चित रूप से एक और तरीका होना चाहिए। मैं शायद [^\\s]+ की तरह कुछ सोच रहा था .. लेकिन उसके लिए उत्पादन किया गया था:

New match: 
    Share1 Disk 
New match: Share1 

... कोई भी विचार?

+0

एक विचार होगा उपयोग करने के लिए '[^ \\ s] +' बजाय: के बाद से बातें हालांकि अपने स्वयं के तर्ज पर कर रहे हैं, आप उपयोग करना है कि चीजें विभाजित है और तरह प्रत्येक पंक्ति के लिए पैटर्न लागू करने के लिए कोशिश कर सकते '। +?'। यदि पाया जाता है तो वह एक सफेद जगह तक पात्रों से मेल खाएगा। – Rahul

+0

@Rahul या '\ S +?' –

+0

दोनों ही [i^\\ s] + 'के समान परिणाम उत्पन्न करते हैं जिन्हें मैंने पहले ही अपने प्रश्न में उल्लेख किया है। मुझे नहीं लगता कि '?' भी बैश में समर्थित है, मेरा मतलब है इस संदर्भ में .. मेरा मतलब है ''' 'के पीछे' '' का मतलब आमतौर पर' अनजान मैच 'होता है। – Forivin

उत्तर

5

यहां कुछ समस्याएं हैं। सबसे पहले, BASH_REMATCH का पहला तत्व संपूर्ण स्ट्रिंग है जो पैटर्न से मेल खाता है, कैप्चर समूह नहीं, इसलिए आप कैप्चर समूहों में उन चीज़ों को प्राप्त करने के लिए ${BASH_REMATCH[@]:1} का उपयोग करना चाहते हैं।

हालांकि, बैश रेगेक्स स्ट्रिंग में कई बार मैचों को दोहराने का समर्थन नहीं करता है, इसलिए शायद इस नौकरी के लिए सही टूल नहीं है।

f=$'\n\tShare1 Disk\n\tShare2 Disk\n\tPrnt1 Printer' 
regex=$'\t(\S+?)\\s+Disk' 
while IFS=$'\n' read -r line; do 
    if [[ $line =~ $regex ]] 
    then 
     printf 'New match: %s\n' "${BASH_REMATCH[@]:1}" 
    else 
     echo "No matches" 
    fi 
done <<<"$f" 
संबंधित मुद्दे