मैं बैश में एक रेगीक्स के साथ एक स्ट्रिंग कैसे मेल कर सकता हूं?


166

मैं एक बैश स्क्रिप्ट लिखने की कोशिश कर रहा हूं, जिसमें एक फ़ंक्शन होता है .tar, जब एक दिया जाता है .tar.bz2, .tar.gzआदि। यह फ़ाइल को डिकम्प्रेस करने के लिए संबंधित स्विच के साथ टार का उपयोग करता है।

मैं प्रयोग कर रहा हूँ अगर elif तो बयान जो यह देखने के लिए फ़ाइलनाम का परीक्षण करता है कि यह किसके साथ समाप्त होता है और मैं इसे रेगेक्स मेटाचैकर का उपयोग करके मिलान करने के लिए नहीं प्राप्त कर सकता हूं।

कमांड लाइन पर मैं 'टेस्ट' का उपयोग कर रही स्क्रिप्ट को लगातार लिखने से बचाने के लिए, मैंने सोचा कि नीचे दिए गए कथन पर काम करना चाहिए, मैंने कोष्ठक, उद्धरण और मेटाकार्टर्स के हर संयोजन को संभव करने की कोशिश की है और अभी भी यह विफल रहता है।

test sed-4.2.2.tar.bz2 = tar\.bz2$; echo $?
(this returns 1, false)

मुझे यकीन है कि समस्या एक सरल है और मैंने हर जगह देखा है, फिर भी मैं यह नहीं कर सकता कि यह कैसे करना है। क्या कोई जानता है कि मैं यह कैसे कर सकता हूं?

जवाबों:


268

रेगेक्स से मिलान करने के लिए आपको =~ऑपरेटर का उपयोग करने की आवश्यकता होती है ।

इसे इस्तेमाल करे:

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched

वैकल्पिक रूप से, आप ==ऑपरेटर के साथ वाइल्डकार्ड (रेगेक्स के बजाय) का उपयोग कर सकते हैं :

[[ sed-4.2.2.tar.bz2 == *tar.bz2 ]] && echo matched

यदि पोर्टेबिलिटी एक चिंता का विषय नहीं है, मैं उपयोग करने की अनुशंसा [[की बजाय [या testयह सुरक्षित और अधिक शक्तिशाली है। देखें कि परीक्षण में क्या अंतर है, [और [?] ब्योरा हेतु।


7
दूसरे उदाहरण में ग्लोब वाइल्डकार्ड से मेल खाते हुए सावधान रहें। [[]] के अंदर, * का विस्तार नहीं किया जाता है जैसा कि आमतौर पर होता है, मौजूदा निर्देशिका में फ़ाइलनामों का मिलान करने के लिए जो एक पैटर्न से मेल खाते हैं। आपका उदाहरण काम करता है, लेकिन यह वास्तव में अति-सामान्यीकरण और गलती से यह मानना ​​आसान है कि * का मतलब कुछ भी मैच करने में है। कोई प्रसंग। यह केवल [[]] के अंदर ही काम करता है। अन्यथा, यह मौजूदा फाइलनामों तक फैलता है।
एलन पोर्टर

7
मैंने regex पर उद्धरणों का उपयोग करने की कोशिश की और असफल रहा; यह जवाब ने इस काम को करने में मदद की, check="^a.*c$";if [[ "abc" =~ $check ]];then echo match;fiहमें regex को var
Aquarius Power

यह भी ध्यान दें कि regexp (perl की तरह) कोष्ठक में नहीं होना चाहिए: [[ sed-4.2.2.tar.bz2 == "*tar.bz2" ]]काम नहीं करेगा।
पाविक ​​२ik

18
FWIW, नकार के लिए वाक्यविन्यास (यानी मेल नहीं खाता ) है [[ ! foo =~ bar ]]
स्किप्पी ले ग्रांड गौरौ

1
डैश -n 1पैरामीटर का समर्थन नहीं करता है , न ही इसे स्वचालित रूप से एक $REPLYचर में रखता है । ध्यान रहे!

54

यह करने के लिए एक समारोह

extract () {
  if [ -f $1 ] ; then
      case $1 in
          *.tar.bz2)   tar xvjf $1    ;;
          *.tar.gz)    tar xvzf $1    ;;
          *.bz2)       bunzip2 $1     ;;
          *.rar)       rar x $1       ;;
          *.gz)        gunzip $1      ;;
          *.tar)       tar xvf $1     ;;
          *.tbz2)      tar xvjf $1    ;;
          *.tgz)       tar xvzf $1    ;;
          *.zip)       unzip $1       ;;
          *.Z)         uncompress $1  ;;
          *.7z)        7z x $1        ;;
          *)           echo "don't know '$1'..." ;;
      esac
  else
      echo "'$1' is not a valid file!"
  fi
}

अन्य नोट

उपरोक्त टिप्पणी में कुंभ पावर के जवाब में, We need to store the regex on a var

चर BASH_REMATCH आपके द्वारा अभिव्यक्ति से मेल खाने के बाद सेट किया गया है, और $ {BASH_REMATCH [n]} को कोष्ठक में लिपटे nth समूह से मेल खाएगा अर्थात निम्नलिखित ${BASH_REMATCH[1]} = "compressed"और शिशुओं में${BASH_REMATCH[2]} = ".gz"

if [[ "compressed.gz" =~ ^(.*)(\.[a-z]{1,5})$ ]]; 
then 
  echo ${BASH_REMATCH[2]} ; 
else 
  echo "Not proper format"; 
fi

(ऊपर दिया गया रेगेक्स फ़ाइल नामकरण और एक्सटेंशन के लिए मान्य नहीं है, लेकिन यह उदाहरण के लिए काम करता है)


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

aजीएनयू टार pपर या बीएसडी टार पर स्पष्ट रूप से विस्तार से संपीड़न प्रकार का अनुमान लगाने के लिए इसे स्पष्ट रूप से बताने के लिए। GNU टार यह स्वचालित रूप से अन्यथा नहीं करेगा, और मैं @GoodPerson की टिप्पणी से अनुमान लगा रहा हूं कि बीएसडी टार डिफ़ॉल्ट रूप से करता है।
मार्क के कोवन

7z अनपैक कर सकता है .. AR, ARJ, CAB, CHM, CPIO, CrAMFS, DMG, EXT, FAT, GPT, HFS, IHEX, ISO, LZH, LZMA, MBR, MSI, MSI, NSIS, NTFS, QCOW2, RAR, RPM, स्क्वैश, अनपैक , UDF, UEFI, VDI, VHD, VMDK, WIM, XAR और Z देखें। 7-zip.org
mosh

14

मेरे पास यहाँ टिप्पणी करने के लिए पर्याप्त प्रतिनिधि नहीं है, इसलिए मैं डॉगबैन के उत्तर पर सुधार करने के लिए एक नया उत्तर प्रस्तुत कर रहा हूं। बिन्दु । regexp में

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched

उदाहरण के लिए, वास्तव में 'tar.bz2' के बीच शाब्दिक बिंदु ही नहीं, किसी भी चरित्र से मेल खाएगा

[[ sed-4.2.2.tar4bz2 =~ tar.bz2$ ]] && echo matched
[[ sed-4.2.2.tar§bz2 =~ tar.bz2$ ]] && echo matched

या ऐसी किसी भी चीज़ के लिए जिसे '' के साथ भागने की आवश्यकता नहीं है। सख्त सिंटैक्स तब होना चाहिए

[[ sed-4.2.2.tar.bz2 =~ tar\.bz2$ ]] && echo matched

या आप और भी कड़े हो सकते हैं और regex में पिछले बिंदु को भी शामिल कर सकते हैं:

[[ sed-4.2.2.tar.bz2 =~ \.tar\.bz2$ ]] && echo matched

9

चूंकि आप बैश का उपयोग कर रहे हैं, इसलिए आपको ऐसा करने के लिए एक बाल प्रक्रिया बनाने की आवश्यकता नहीं है। यहाँ एक समाधान है जो इसे पूरी तरह से बैश में करता है:

[[ $TEST =~ ^(.*):\ +(.*)$ ]] && TEST=${BASH_REMATCH[1]}:${BASH_REMATCH[2]}

स्पष्टीकरण: "कॉलन और एक या अधिक रिक्त स्थान" अनुक्रम से पहले और बाद के समूह BASH_REMATCH सरणी में पैटर्न मैच ऑपरेटर द्वारा संग्रहीत किए जाते हैं।


1
ध्यान दें कि इंडेक्स 0 में पूरा मैच होता है और इंडेक्स 1 और 2 में ग्रुप मैच होते हैं।
रेनर

3
if [[ $STR == *pattern* ]]
then
    echo "It is the string!"
else
    echo "It's not him!"
fi

मेरे लिये कार्य करता है! GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)


1
यह बेहद खतरनाक है; यह केवल आपके लिए अपरिभाषित व्यवहार के बिना व्यवहार करता है क्योंकि आपके पास वर्तमान निर्देशिका में कोई फाइल नहीं है जिसका नाम शाब्दिक विकल्प "पैटर्न" है। आगे बढ़ो, इस तरह नामित कुछ फ़ाइलों को बनाएं, और विस्तार करने वाली फाइलें फाइलों से मेल खाएगी और बहुरंगी हाइजीन के साथ सब कुछ तोड़ देगी।
०३६__

लेकिन मैंने एक प्रयोग किया है: फ़ाइलों के साथ `1पट्टर्न, पैटर्न pattern2 और वर्तमान निर्देशिका में पैटर्न। यह स्क्रिप्ट उम्मीद के मुताबिक काम करती है। क्या आप मुझे अपना परीक्षा परिणाम प्रदान कर सकते हैं? @ i336_
जुआन

2
@ i336: मुझे ऐसा नहीं लगता। भीतर [[ ... ]], आरएचएस ग्लोब पैटर्न वर्तमान निर्देशिका के अनुसार विस्तार नहीं करता है , जैसा कि आमतौर पर होता है।
user1934428

@ i336_ नहीं [[...]], बैश फ़ाइल नाम विस्तार नहीं करता है। बैश मैनुअल में,Word splitting and filename expansion are not performed on the words between the [[ and ]];
जिनबीम होंग

@jinbeomhong: टीआईएल। यह जानना अच्छा है, धन्यवाद!
०३६__

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