यदि कोई चर खाली है या केवल रिक्त स्थान हैं तो मैं कैसे परीक्षण कर सकता हूं?


240

paramखाली न होने पर निम्नलिखित बैश सिंटैक्स की पुष्टि करता है:

 [[ !  -z  $param  ]]

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

param=""
[[ !  -z  $param  ]] && echo "I am not zero"

कोई आउटपुट और इसका ठीक नहीं।

लेकिन जब paramएक (या अधिक) अंतरिक्ष वर्णों को छोड़कर खाली होता है, तो मामला अलग होता है:

param=" " # one space
[[ !  -z  $param  ]] && echo "I am not zero"

"मैं शून्य नहीं हूँ" आउटपुट है।

मैं उन चर पर विचार करने के लिए परीक्षण को कैसे बदल सकता हूं जिनमें केवल रिक्त स्थान के रूप में वर्ण हैं?


4
से man test: -z STRING - the length of STRING is zero। यदि आप सभी रिक्त स्थान हटाना चाहते हैं $param, तो उपयोग करें${param// /}
dchirikov

6
वाह, वहाँ एक साधारण trim()समारोह में किसी भी * निक्स के लिए बिलकुल नहीं है ? इतने सरल कुछ हासिल करने के लिए कई अलग-अलग हैक्स ...
ADTC

6
@ADTC $ (sed 's / ^ \ s + | \ s + $ // g' <<< $ string) मेरे लिए काफी सरल लगता है। पहिया को क्यों मजबूत करें?
jbowman

3
क्योंकि यह shinier हो सकता है
Inversus

1
बस ध्यान देने योग्य है कि [[ ! -z $param ]]बराबर है test ! -z $param
नूह ससमान

जवाबों:


292

पहले, ध्यान दें कि -zपरीक्षण स्पष्ट रूप से इसके लिए है:

स्ट्रिंग की लंबाई शून्य है

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

आप जो चाहते हैं वह पैटर्न प्रतिस्थापन पैरामीटर विस्तार का उपयोग करके चर से रिक्त स्थान को निकालना है :

[[ -z "${param// }" ]]

यह paramचर का विस्तार करता है और पैटर्न (एकल स्थान) के सभी मैचों को कुछ भी नहीं के साथ बदल देता है , इसलिए एक स्ट्रिंग जिसमें केवल रिक्त स्थान है उसे एक खाली स्ट्रिंग में विस्तारित किया जाएगा।


कि कैसे काम करता है की बुनियादी तथ्य यह है कि ${var/pattern/string}के पहले सबसे लंबे समय तक मैच की जगह patternके साथ string। जब patternशुरू होता है /(ऊपर के रूप में) तो यह सभी मैचों को बदल देता है । क्योंकि प्रतिस्थापन खाली है, हम अंतिम /और stringमूल्य को छोड़ सकते हैं :

$ {पैरामीटर / पैटर्न / स्ट्रिंग}

पैटर्न बस फ़ाइलनाम विस्तार में के रूप में एक पैटर्न का उत्पादन करने के लिए विस्तारित किया गया है। पैरामीटर का विस्तार किया गया है और इसके मूल्य के खिलाफ पैटर्न का सबसे लंबा मैच स्ट्रिंग के साथ बदल दिया गया है । अगर पैटर्न '/' से शुरू होता है, के सभी मैचों पैटर्न बदल दिए जाते हैं स्ट्रिंग । आम तौर पर केवल पहले मैच को बदल दिया जाता है। ... यदि स्ट्रिंग शून्य है, तो पैटर्न के मिलान हटा दिए जाते हैं और / निम्नलिखित पैटर्न छोड़ा जा सकता है।

आखिरकार, हम ${param// }सभी स्थानों को हटाने के लिए समाप्त होते हैं ।

ध्यान दें कि हालांकि ksh(जहां यह उत्पन्न हुआ) में मौजूद है , zshऔर bash, वह वाक्य रचना POSIX नहीं है और इसका उपयोग shलिपियों में नहीं किया जाना चाहिए ।


sedउन्होंने कहा कि उपयोग ... बस echoचर उन्होंने कहा ...
mikezter

1
हम्म। यदि यह है ${var/pattern/string}तो यह [[ -z ${param/ /} ]]स्लैश के बीच की जगह के साथ नहीं होना चाहिए पैटर्न और स्ट्रिंग के बाद कुछ भी नहीं है?
जेसी चिशोल्म

@JesseChisholm "क्योंकि प्रतिस्थापन खाली है, हम अंतिम / और स्ट्रिंग मान को छोड़ सकते हैं"; "यदि स्ट्रिंग शून्य है, तो पैटर्न के मिलान हटा दिए जाते हैं और / निम्नलिखित पैटर्न छोड़ा जा सकता है।"
माइकल होमर

6
@ मिचेलहोमर उत्तर [[ -z "${param// }" ]]सुनिश्चित करता है patternकि खाली है और replacement stringएक ही स्थान है। आह! मैं देख रहा हूँ अब if pattern begins with a slashमुझे वह हिस्सा याद आ गया। इसलिए पैटर्न है / और स्ट्रिंग बंद है और इसलिए खाली है। धन्यवाद।
जेसी चिशोल्म

bash नोट: यदि सेट -o nounset (set -u) में चल रहा है, और param unset (null या space-fill) के बजाय है, तो यह एक अनबाउंड वैरिएबल एरर उत्पन्न करेगा। (सेट + यू; .....) इस परीक्षा को छूट देगा।
ब्रायन क्रिसमैन

31

यह जांचने का आसान तरीका है कि एक स्ट्रिंग में केवल एक अधिकृत सेट में वर्ण हैं, अनधिकृत वर्णों की उपस्थिति के लिए परीक्षण करना है। इस प्रकार, यह परीक्षण करने के बजाय कि क्या स्ट्रिंग में केवल रिक्त स्थान हैं, परीक्षण करें कि क्या स्ट्रिंग में अंतरिक्ष के अलावा कुछ वर्ण हैं। बैश में, ksh या zsh:

if [[ $param = *[!\ ]* ]]; then
  echo "\$param contains characters other than space"
else
  echo "\$param consists of spaces only"
fi

"रिक्त स्थान से मिलकर बनता है" में रिक्त (या परेशान) चर का मामला शामिल है।

आप किसी भी व्हाट्सएप चरित्र के लिए परीक्षण करना चाह सकते हैं। स्थान, टैब या न्यूलाइन का परीक्षण करने के [[ $param = *[^[:space:]]* ]]लिए, लोकल सेटिंग्स का उपयोग करने के लिए या व्हाट्सएप वर्णों की स्पष्ट सूची का उपयोग करने के लिए उपयोग करें [[ $param = *[$' \t\n']* ]]

=अंदर के साथ एक पैटर्न के खिलाफ एक स्ट्रिंग मिलान [[ … ]]करना एक ksh एक्सटेंशन है (यह भी bash और zsh में मौजूद है)। किसी भी बॉर्न / पोसिक्स-शैली में, आप caseएक पैटर्न के खिलाफ एक स्ट्रिंग से मेल करने के लिए निर्माण का उपयोग कर सकते हैं । ध्यान दें कि मानक शेल पैटर्न !एक चरित्र सेट को नकारने के लिए उपयोग करते हैं, बजाय ^सबसे नियमित अभिव्यक्ति सिंटैक्स में।

case "$param" in
  *[!\ ]*) echo "\$param contains characters other than space";;
  *) echo "\$param consists of spaces only";;
esac

$'…'व्हाट्सएप पात्रों के लिए परीक्षण करने के लिए, वाक्य-विन्यास ksh / bash / zsh के लिए विशिष्ट है; आप इन वर्णों को अपनी लिपि में शाब्दिक रूप से सम्मिलित कर सकते हैं (ध्यान दें कि एक नई पंक्ति को उद्धरण के भीतर होना चाहिए, क्योंकि बैकस्लैश + न्यूलाइन कुछ भी नहीं फैलता है), या उन्हें उत्पन्न करता है, जैसे।

whitespace=$(printf '\n\t ')
case "$param" in
  *[!$whitespace]*) echo "\$param contains non-whitespace characters";;
  *) echo "\$param consists of whitespace only";;
esac

यह लगभग उत्कृष्ट है - लेकिन, जैसा कि अभी तक, यह पूछे गए सवाल का जवाब नहीं देता है। यह वर्तमान में आपको एक अनसेट या खाली शेल वैरिएबल और केवल रिक्त स्थान के बीच अंतर बता सकता है । यदि आप मेरे सुझाव को स्वीकार करेंगे तो आप परम विस्तार फॉर्म को अभी तक किसी भी अन्य उत्तर द्वारा परिवर्तित नहीं करेंगे जो स्पष्ट रूप से सेट होने के लिए एक शेल चर का परीक्षण करता है - मेरा मतलब है ${var?not set}- उस परीक्षा को पास करना और जीवित रहना यह सुनिश्चित करेगा कि आपके द्वारा मिलान किया गया चर *) caseनिश्चित रूप से प्रभावित होगा उदाहरण के लिए, उत्तर।
मोकेसर 2

सुधार - यह, वास्तव में, मूल रूप से पूछे गए प्रश्न का उत्तर देगा , लेकिन इसे इस तरह से संपादित किया गया है कि यह मूल रूप से प्रश्न का अर्थ बदल देता है और इसलिए आपके उत्तर को अमान्य कर देता है।
मिकसर्व

आप की जरूरत [[ $param = *[!\ ]* ]]में mksh
स्टीफन चेजलस

20

POSIXly:

case $var in
  (*[![:blank:]]*) echo '$var contains non blank';;
  (*) echo '$var contains only blanks or is empty or unset'
esac

रिक्त , गैर-रिक्त , खाली , परेशान के बीच अंतर करने के लिए :

case ${var+x$var} in
  (x) echo empty;;
  ("") echo unset;;
  (x*[![:blank:]]*) echo non-blank;;
  (*) echo blank
esac

[:blank:]क्षैतिज रिक्ति वर्णों (ASCII में स्थान और टैब) के लिए है, लेकिन आपके लोकेल में संभवतः कुछ और हैं, कुछ सिस्टम में गैर-ब्रेकिंग स्पेस (जहां उपलब्ध है), कुछ शामिल नहीं होंगे)। अगर आप वर्टिकल स्पेसिंग कैरेक्टर्स (जैसे कि न्यूलाइन या फॉर्म-फीड) चाहते हैं, तो उसके [:blank:]साथ बदलें [:space:]


POSIXly आदर्श है क्योंकि यह (यकीनन बेहतर) डैश के साथ काम करेगा।
केन शार्प

zshलगता है कि [![:blank:]]इसके साथ समस्या है , यह :bअमान्य संशोधक है। में shऔर kshअनुकरण, यह घटना के लिए नहीं मिला[
cuonglm

@cuonglm, आपने क्या प्रयास किया? var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'मेरे लिए ठीक है। नहीं मिला घटना केवल इंटरैक्टिव गोले के लिए होगा।
स्टीफन चेजालस

@ स्टीफनचेज़ेलस: आह, ठीक है, मैंने इंटरेक्टिव गोले के साथ कोशिश की। :bअवैध संशोधक थोड़ा अजीब है।
कोउंगलम

1
@FranklinYu, ओएस पर / एक्स shहै bashके साथ बनाया गया --enable-xpg-echo-defaultहै और --enable-strict-posix-defaultइसलिए यूनिक्स अनुरूप (जो शामिल होने के लिए के रूप में echo '\t'एक टैब outputting)।
स्टीफन चेजलस

4

एक अच्छी स्क्रिप्टिंग भाषा में एक स्क्रिप्ट के बजाय एक शेल स्क्रिप्ट लिखने का एकमात्र शेष कारण है , अगर चरम पोर्टेबिलिटी एक चिंताजनक चिंता है। विरासत /bin/shकेवल एक चीज है जिसे आप निश्चित कर सकते हैं, लेकिन उदाहरण के लिए पर्ल बैश की तुलना में क्रॉस-प्लेटफॉर्म उपलब्ध होने की अधिक संभावना है। इसलिए, कभी भी शेल स्क्रिप्ट न लिखें जो उन सुविधाओं का उपयोग करती हैं जो वास्तव में सार्वभौमिक नहीं हैं - और ध्यान रखें कि कई मालिकाना यूनिक्स विक्रेता POSIX.1-2001 से पहले अपने शेल वातावरण को फ्रीज करते हैं

इस परीक्षण को करने का एक पोर्टेबल तरीका है, लेकिन आपको इसका उपयोग करना होगा tr:

[ "x`printf '%s' "$var" | tr -d "$IFS"`" = x ]

(डिफ़ॉल्ट रूप से $IFS, सुविधापूर्वक, एक स्थान, एक टैब और एक नई पंक्ति है।)

( printfबिल्टिन अपने आप में बहुत ही पोर्टेबल है, लेकिन इस पर भरोसा करना आपके लिए कौन सा संस्करण है, यह पता लगाने की तुलना में बहुत कम परेशानी echoहै।)


1
यह थोड़ा जटिल है। एक स्ट्रिंग निश्चित वर्ण हैं कि क्या परीक्षण करने के लिए हमेशा की तरह पोर्टेबल तरीका है के साथcase
गाइल्स

@ गिल्स मुझे नहीं लगता कि caseएक स्ट्रिंग का पता लगाने के लिए एक ग्लोब लिखना संभव है जो या तो खाली है, या जिसमें केवल व्हाट्सएप अक्षर हैं। (यह एक regexp के साथ आसान होगा, लेकिन caseregexps नहीं करता है। आपके उत्तर में निर्माण काम नहीं करेगा यदि आप newlines की परवाह करते हैं।)
zwol

1
मैंने अपने उत्तर में एक उदाहरण के रूप में स्थान दिया क्योंकि यही प्रश्न पूछा गया था। व्हाट्सएप पात्रों के लिए परीक्षण करना उतना ही आसान है case $param in *[![:space:]]*) …:। यदि आप IFSपात्रों के लिए परीक्षण करना चाहते हैं , तो आप पैटर्न का उपयोग कर सकते हैं *[$IFS]*
गाइल्स

1
@mikeserv वास्तव में गंभीर रूप से रक्षात्मक स्क्रिप्ट में, आपने <space><tab><newline>शुरुआत में IFS को स्पष्ट रूप से सेट किया और फिर इसे फिर कभी नहीं छुआ। मैंने सोचा था कि यह एक विकर्षण होगा।
zwol

1
पैटर्न में चर के बारे में, मुझे लगता है कि सभी बॉर्न संस्करणों और सभी पोसिक्स गोले में काम करता है; मामले के पैटर्न का पता लगाने और परिवर्तनीय विस्तार को बंद करने के लिए अतिरिक्त कोड की आवश्यकता होगी और मैं इसे करने के लिए एक कारण के बारे में नहीं सोच सकता। मेरे पास इसके कुछ उदाहरण हैं, .profileजिन्हें कई बॉर्न शेल द्वारा निष्पादित किया गया है। बेशक [$IFS]क्या इरादा था, तो काम नहीं चलेगा IFSकुछ गैर मूलभूत मूल्यों (खाली (या सेट), युक्त है ], के साथ शुरू करने !या ^)।
गाइल्स

4
if [[ -n "${variable_name/[ ]*\n/}" ]]
then
    #execute if the the variable is not empty and contains non space characters
else
    #execute if the variable is empty or contains only spaces
fi

यह किसी भी सफेद अंतरिक्ष चरित्र से छुटकारा दिलाता है, न कि केवल एक ही स्थान, सही? धन्यवाद
अलेक्जेंडर मिल्स

0

परीक्षण के लिए यदि चर रिक्त है या रिक्त स्थान हैं, तो आप इस कोड का भी उपयोग कर सकते हैं:

${name:?variable is empty}

2
मुझे लगता है कि आपका जवाब नीचे दिया गया है क्योंकि "या रिक्त स्थान शामिल हैं" सच नहीं है।
बर्नहार्ड

सावधान रहें - जो वर्तमान शेल को मारता है। इसे लगाने के लिए बेहतर है: ($ {उपधारा?})। इसके अलावा - कि stderr को लिखेंगे - आप शायद पुनर्निर्देशन चाहते हैं। और सबसे महत्वपूर्ण है जो चर के वास्तविक मूल्य का मूल्यांकन करता है यदि यह परेशान या अशक्त नहीं है। अगर वहां कोई कमांड है, तो आप इसे चला रहे हैं। उस परीक्षण को चलाना सबसे अच्छा है :
mikeserv

यह शेल को कैसे मारेगा। और आप इसका परीक्षण भी कर सकते हैं, पहले इसे परिभाषित करें name=aaaaफिर इस कमांड को चलाएं यह echo ${name:?variable is empty}वेरिएबल नाम के मान को प्रिंट करेगा और अब इस कमांड echo ${name1:?variable is empty}को प्रिंट करें -sh: name1: वेरिएबल खाली है
pratik

हां - echo ${name:?variable is empty}या तो $nameगैर-शून्य मान का मूल्यांकन करेगा या यह शेल को मार देगा। तो उसी कारण से आपको नहीं करना prompt > $randomvarचाहिए और न ${var?}ही - अगर वहाँ एक कमांड है, तो यह शायद चलने वाला है - और आपको नहीं पता कि यह क्या है। एक इंटरैक्टिव शेल से बाहर निकलने की ज़रूरत नहीं है - यही कारण है कि आपका नहीं है। फिर भी, यदि आप कुछ परीक्षण देखना चाहते हैं, तो उनमें से बहुत सारे हैं। यह काफी लंबा नहीं है ...
mikeserv

0

यह जाँचने के लिए कि क्या कोई चर अशक्त है, खाली है (शून्य मान है) या केवल रिक्त स्थान हैं:

 [ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"

स्पष्टीकरण:

  • ${param%%[! ]*}पहले गैर-स्थान से अंत तक हटाए जाने का विस्तार ।
  • यह केवल प्रमुख स्थानों को छोड़ देता है।
  • अगला विस्तार चर से प्रमुख रिक्त स्थान को निकालता है।
  • यदि परिणाम खाली है, तो चर को शुरू करने के लिए या तो खाली था।
  • या, यदि चर खाली नहीं था, तो प्रमुख रिक्त स्थान को हटाकर इसे खाली कर दिया।
  • अगर परिणाम खाली है -z, तो गूंज empty

उपरोक्त POSIX संगत है और किसी भी बॉर्न वंशज में चलता है।

यदि आप उस टैब को भी विस्तारित करना चाहते हैं, तो एक स्पष्ट टैब शामिल करें:

 [ -z "${param#"${param%%[!     ]*}"}" ] && echo "empty"

या आपके द्वारा हटाए गए वर्णों के साथ एक चर का उपयोग करें:

 var=$' \t'   # in ksh, bash, zsh
 [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"

या आप कुछ POSIX "वर्ण वर्ग अभिव्यक्ति" (रिक्त स्थान और टैब का उपयोग कर सकते हैं) का उपयोग कर सकते हैं:

 [ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"

लेकिन यह mksh, lksh और पॉश में विफल हो जाएगा।


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