मैं बैश स्क्रिप्ट में नियमित अभिव्यक्तियों के साथ एक परीक्षा को कैसे नकार सकता हूं?


173

GNU बैश (संस्करण 4.0.35 (1) -release (x86_64-suse-linux-gnu) का उपयोग करते हुए, मैं रेगुलर एक्सप्रेशंस के साथ एक टेस्ट को नकारना चाहूंगा। उदाहरण के लिए, मैं सशर्त रूप से PATH वैरिएबल में एक पथ जोड़ना चाहूंगा। यदि पथ पहले से ही वहां नहीं है, जैसे कि:

TEMP=/mnt/silo/bin
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi
TEMP=/mnt/silo/Scripts:
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi
TEMP=/mnt/silo/local/bin
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi
export PATH

मुझे यकीन है कि ऐसा करने के लिए एक लाख तरीके हैं, लेकिन मैं यह जानना चाहूंगा कि क्या सशर्त किसी भी तरह से नकारा जा सकता है, जैसे कि (गलत):

TEMP=/mnt/silo/bin
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi
TEMP=/mnt/silo/Scripts:
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi
TEMP=/mnt/silo/local/bin
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi
export PATH

जवाबों:


193

आपके पास यह सही था, बस !और [[जैसे के बीच एक स्थान रखाif ! [[


14
ओये वी! बस जब मैं सुरक्षित रूप से पर्ल के अंतःक्रियात्मक विशेष चरित्र पागलपन को सुरक्षित करता हूं, तो मैं खुद को बैश स्पेस (प्लेसमेंट) में खो देता हूं! (मुझे लगता है कि मेरे अजगर को अजगर की तरह डर लगता है।) धन्यवाद!
डेविड रोजर्स

126

आप कोष्ठक के अंदर विस्मयादिबोधक चिह्न भी लगा सकते हैं:

if [[ ! $PATH =~ $temp ]]

लेकिन आपको झूठी सकारात्मकता को कम करने के लिए अपने पैटर्न का लंगर डालना चाहिए:

temp=/mnt/silo/bin
pattern="(^|:)${temp}(:|$)"
if [[ ! "${PATH}" =~ ${pattern} ]]

जो पहले या उसके बाद (या दोनों) एक बृहदान्त्र के साथ शुरुआत या अंत में मैच की तलाश करता है। मैं शेल चर के साथ नाम टकराव की संभावना को कम करने की आदत के रूप में लोअरकेस या मिश्रित केस वैरिएबल नामों का उपयोग करने की सलाह देता हूं।


आह, एंकरिंग के बारे में याद दिलाने के लिए धन्यवाद। लोअरकेस या मिश्रित वैरिएबल नामों का उपयोग करने का विचार एक शुरुआती व्यक्ति को भ्रमित कर रहा है, क्योंकि मैंने अब तक जो सलाह देखी है वह अपरकेस का उपयोग करना है। मुझे समझ में आ रहा है कि आप क्या कर रहे हैं, लेकिन मैंने रसोई की किताब से (मेरी समझ से) आराम से भटकने के लिए पर्याप्त बाश स्क्रिप्टिंग उदाहरण नहीं देखे हैं।
डेविड रोजर्स

4
@anyoneis इस पर हमें भरोसा करते हैं। उपयोगकर्ता द्वारा परिभाषित अपरकेस चर के उपयोग से बचा जाना चाहिए। बैश में सभी चरों का विस्तार किया जाता है, $ताकि उन्हें बाहर खड़ा करने के लिए उन्हें अपरकेस करने का कोई कारण न हो।
सेजएक्स

मुझे इससे if [[ ! $foo =~ bar ]]अधिक सुरक्षित लगता है if ! [[ $foo =~ bar ]], क्योंकि इससे अधिक परिस्थितियों को पेश करना आसान हो जाता हैif
CTodea


9

हां, आप परीक्षण को नकार सकते हैं क्योंकि घेराबंदी पहले ही इंगित कर चुकी है।

हालाँकि आपको इसके लिए नियमित अभिव्यक्तियों का उपयोग नहीं करना चाहिए - यदि आपका पथ विशेष वर्णों का है तो यह विफल हो सकता है। इसके बजाय यह प्रयास करें:

[[ ":$PATH:" != *":$1:"* ]]

(स्रोत)


1
इस रूप का उपयोग करने का एक और कारण यह है कि यह गलती से सब्सट्रैटिंग से मेल नहीं खाएगा (जैसे कि पथ में "/ बिन" जोड़ने में विफल रहता है क्योंकि "/ usr / बिन" पहले से ही है)।
गॉर्डन डेविसन

मुझे यह समझने में थोड़ा समय लगा कि बाईं ओर के कॉलोनों ने मुझे वह एंकरिंग कैसे दी जो मैं चाहता था। खोजे जाने वाले स्ट्रिंग में सामग्री जोड़कर पैटर्न को कम करने का विचार याद रखने योग्य है। मुझे समझ नहीं आ रहा है कि पथ में विशेष वर्ण रेगेक्स समाधान को क्यों बाधित करेंगे, लेकिन बैश पैटर्न समाधान नहीं। क्या आप मुझे एक उदाहरण दे सकते हैं?
डेविड रोजर्स

मुझे नहीं लगता कि यह सभी मामलों में मज़बूती से काम करेगा। बेहतर IMHO में रेगेक्स मिलान
फेलिप अल्वारेज़

5

मैं ऐसे मामलों में सशर्त ऑपरेटरों का उपयोग किए बिना कोड को सरल बनाना पसंद करता हूं:

TEMP=/mnt/silo/bin
[[ ${PATH} =~ ${TEMP} ]] || PATH=$PATH:$TEMP
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.