बैश स्क्रिप्ट में नियमित अभिव्यक्ति


12

यह मेरी पहली बार की गई स्क्रिप्टिंग है इसलिए मैं शायद एक आसान गलती कर रहा हूं।

मूल रूप से, मैं एक स्क्रिप्ट लिखने की कोशिश कर रहा हूं जो उपयोगकर्ता के समूह को प्राप्त करता है, और यदि वे एक निश्चित समूह में हैं, तो यह उसी के अनुसार लॉग करेगा। जाहिर है, वहाँ अधिक कार्यक्षमता होगी, लेकिन कोई बिंदु निर्माण नहीं है कि जब मैं भी regex काम नहीं कर सकता!

अब तक, मेरे पास यह है:

#!/bin/bash

regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"

# example output
groups="username : username usergroup"

echo "$groups" >> /home/jrdn/log

if [[ "$groups" =~ $regex ]]; then
    echo "Match!" >> /home/jrdn/log
else
    echo "No match" >> /home/jrdn/log
fi

हर जगह मैंने कोशिश की है कि regex, यह काम करता है। लेकिन बाश स्क्रिप्ट में, यह केवल कभी आउटपुट देता है $groups, उसके बाद No match। तो क्या कोई मुझे बता सकता है कि इसमें क्या गलत है?


1
क्या आपको लगता है कि इसके साथ कुछ भी गलत है?
मैनटवर्क

1
@jrdnhannah फिर धीरे-धीरे अपने लक्ष्य regexp को बनाने की कोशिश करें, पहले मैच ^([a-zA-Z0-9\-_]+)फिर कोलन वगैरह जोड़ें ... आपको बहुत जल्द पता लगाना चाहिए कि समस्या कहां है।
पीटर

2
यहां बैश 4.2.45 के साथ है। अंडरस्कोर को बचाते हुए इसे तय किया। अजीब। @jrdnhannah क्या आप इसे उत्तर के रूप में लिख सकते हैं और कृपया इसे स्वीकार कर सकते हैं?
terdon

1
चूंकि मैंने केवल यूनिक्स एसई पर हस्ताक्षर किए हैं, इसलिए मुझे अपना जवाब देने से पहले 8 घंटे इंतजार करना होगा। उत्तर के रूप में चिह्नित करने के लिए खुश अगर कोई और करता है, हालांकि।
15

4
@terdon bash सिर्फ libc के regex फ़ंक्शन को कॉल करता है, शायद। तो यह libc संस्करण पर निर्भर करता है, न कि bash संस्करण पर। मेरा उत्तर (या हो सकता है यहां तक कि मिलान क्रम पर आपके उपयोग में हैं) देखें ...
derobert

जवाबों:


13

से man 7 regex:

एक ब्रैकेट अभिव्यक्ति "[]" में संलग्न वर्णों की एक सूची है। ...

... शाब्दिक '-' को शामिल करने के लिए, इसे पहला या अंतिम चरित्र बनाएं ...। [A] '' सहित अन्य विशेष वर्ण, एक ब्रैकेट अभिव्यक्ति के भीतर अपना विशेष महत्व खो देंगे।

Egrep के साथ regexp को आज़माना एक त्रुटि देता है:

$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end

यहाँ एक सरल संस्करण है, जो एक त्रुटि भी देता है:

$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end

चूँकि \यह विशेष नहीं है, यह एक सीमा है, ठीक उसी तरह जैसे [a-z]। आपको अपना -अंत पसंद करने की आवश्यकता है , जैसे [_-]या:

echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup

यह आपके libc संस्करण की परवाह किए बिना काम करना चाहिए (या तो egrep या बैश में)।

संपादित करें: यह वास्तव में आपकी स्थानीय सेटिंग्स पर भी निर्भर करता है। मैनपेज इस बारे में चेतावनी देता है:

रंग बहुत टकराव-अनुक्रम-निर्भर हैं, और पोर्टेबल कार्यक्रमों को उन पर भरोसा करने से बचना चाहिए।

उदाहरण के लिए:

$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'
\_

बेशक, भले ही यह त्रुटि नहीं हुई, यह वह नहीं है जो आप चाहते हैं:

$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'
\^_

यह एक सीमा है, ASCII में, शामिल है, जो है \, [, ^, और _


दिलचस्प। मेरी egrepकोई त्रुटि नहीं है, बस इसे सही ढंग से मेल खाता है।
manatwork

@manatwork अपने मिलान अनुक्रम शायद अनुमति देता रेंज ....
derobert

मैं टकराव के बारे में ज्यादा नहीं जानता। आपका यह मतलब है LC_COLLATE="en_US.UTF-8":?
मैनटवर्क

@manatwork मैंने एक उदाहरण देने के लिए प्रश्न को संपादित किया है। ध्यान दें कि यह आपके सिस्टम पर भिन्न हो सकता है, क्योंकि कभी-कभी उन टकराव (छंटनी) अनुक्रम बदल जाते हैं।
derobert

1
इसके ठीक @manatwork, मैं लगभग एक बग रिपोर्ट दायर करने से पहले मैं से बचने के लिए प्रयास देखा -...
derobert

4

Regexps (और कोड के बड़े टुकड़ों में किसी भी कीड़े) के साथ सामान्य नियम: इसे काट दें और इसे चरण दर चरण पुन: बनाएँ या बाइसेक्टिंग का उपयोग करें - जो भी आपके लिए बेहतर काम करता है।

इस मामले में अपराधी अंडरस्कोर निकला - बैकस्लैश के साथ भागने से यह काम हो गया है।

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