'If [$ 1 = "1"] शाखा हमेशा $ 1 नहीं होने पर भी क्यों चुनी जाती है?


10

मेरे पास 'teleport.sh' नामक एक शेल स्क्रिप्ट है:

if [ $1="1" ];
    then
    shift
        mv "$@" ~/lab/Sun
elif [ $1="2" ];
    then
    shift
        mv "$@" ~/lab/Moon
elif [ $1="3" ];
    then
    shift
        mv "$@" ~/lab/Earth
fi

जब मैं निष्पादित करता हूं:

sh teleport.sh 2 testfile

यह निर्देशिका testfileमें ले जाया जाता है ~/lab/Sun, जो मुझे बहुत भ्रमित करता है क्योंकि मैंने उस स्क्रिप्ट में 1 या '1' पास नहीं किया था।

यहाँ क्या गलत है?


1
लैब , सूर्य , चंद्रमा , पृथ्वी और टेलीपोर्ट के लिए +1 । लेकिन आपको चाहिए हमेशा दोहरे उद्धरण विस्तार ( $var, $(cmd)और यहां तक कि `cmd`[जो करने के लिए $(cmd)प्राथमिकता दी जानी चाहिए])। कुछ किनारे मामले हैं जहां आपको उद्धृत करने की आवश्यकता नहीं है , लेकिन हमेशा ऐसा करने से चोट नहीं पहुंचेगी।
nyuszika7h

@ nyuszika7h, दोहरे उद्धरण का मतलब "$ var" और "$ cmd" नहीं होना चाहिए? ऊपर बताए गए गोल कोष्ठक का क्या लाभ है?
ज़ेन

$(cmd)है आदेश प्रतिस्थापन , (अधिकतर) के रूप में ही `cmd`। देखें mywiki.wooledge.org/CommandSubstitution और mywiki.wooledge.org/BashFAQ/082
nyuszika7h

जवाबों:


19

रिक्त स्थान का उपयोग आपकी समस्या को ठीक करता है।

if [ "$1" = 1 ];
    then
    shift
        mv "$@" ~/lab/Sun
elif [ "$1" = 2 ];
    then
    shift
        mv "$@" ~/lab/Moon
elif [ "$1" = 3 ];
    then
    shift
        mv "$@" ~/lab/Earth
fi

हालांकि यह शून्य है:

#!/bin/bash

action=$1
shift
files=("$@")
case $action in  
  1) mv -- "${files[@]}" ~/lab/Sun     ;;
  2) mv -- "${files[@]}" ~/lab/Moon    ;;
  3) mv -- "${files[@]}" ~/lab/Earth   ;;
esac

3
हां, रिक्त स्थान आवश्यक हैं, लेकिन मैं सोच रहा हूं कि मूल $1="1"वाक्यविन्यास "सही" (सही परिणाम पैदा करने) पर क्यों काम करता है। [/ testबिलिन वास्तव में उस अभिव्यक्ति की व्याख्या कैसे करता है ?
echristopherson

5
@echristopherson रिक्त स्थान के बिना, testकेवल एक तर्क (एक "एल-मूल्य") देखता है। अन्य तर्कों के बिना (एक "ऑपरेटर" और एक "आर-वैल्यू"), परीक्षण करने के लिए कुछ भी नहीं है, इसलिए testबस कहता है "ठीक है, ठीक है, हाँ, आपने मुझे कुछ दिया है और यह रिक्त रूप से सच होना चाहिए"।
बिशप

2
$1="1"है $1द्वारा concatenated=1
jdh8

मामले का उपयोग करते समय, शर्तों में से कोई भी पूरा नहीं होने पर निष्पादित करने के लिए एक कार्रवाई कैसे सेट करें?
ज़ेन

11

पहली स्पष्ट बात यह है कि आपको तर्क के बीच रिक्त स्थान प्रदान करना चाहिए [, testया [[:

if [ "$1" = 1 ];

जब बैश में, का उपयोग करने [[ ]]की सिफारिश की जाती है क्योंकि यह सशर्त अभिव्यक्ति के लिए अनावश्यक चीजों को नहीं करता है जैसे शब्द विभाजन और pathname विस्तार। दोहरे उद्धरण चिह्नों के आसपास भी उद्धृत करने की आवश्यकता नहीं है। अधिक पठनीय ऑपरेटर ==का भी उपयोग किया जा सकता है।

if [[ $1 == 1 ]];

जोड़ा ध्यान दें: दूसरे संकार्य भी चर होते हैं, के हवाले से आवश्यक है के रूप में यह पैटर्न मिलान के अधीन हो सकता है, तो ऐसा लगता है कि पहचानने योग्य वर्ण हैं *, ?, [], आदि .. तो ग्लोबिंग बढ़ाया या पैटर्न मिलान के साथ सक्षम किया गया है shopt -s extglob, अन्य रूपों की तरह @(), !()आदि पैटर्न के रूप में भी पहचाना जाएगा। पैटर्न मिलान देखें ।

जैसे ऑपरेटरों के साथ <और >यह अभी भी आवश्यक हो सकता है क्योंकि मैंने एक बार एक बग का सामना किया था जहां दूसरे तर्क को उद्धृत नहीं करने के कारण अलग-अलग परिणाम हुए।

पहले ऑपरेंड के लिए, कुछ भी लागू नहीं होता है।

इस सरल भिन्नता पर भी विचार करें:

case "$1" in
1)
    mv -- "${@:2}" ~/lab/Sun
    ;;
2)
    mv -- "${@:2}" ~/lab/Moon
    ;;
3)
    mv -- "${@:2}" ~/lab/Earth
    ;;
esac

या संघनित:

case "$1" in
1) mv -- "${@:2}" ~/lab/Sun ;;
2) mv -- "${@:2}" ~/lab/Moon ;;
3) mv -- "${@:2}" ~/lab/Earth ;;
esac

"${@:2}"विकल्प का एक रूप है विस्तार या सरणी सदस्य विस्तार जहां 2ऑफसेट है। यह दूसरे मूल्य पर विस्तार शुरू करता है। इसके साथ हमें उपयोग करने की आवश्यकता नहीं हो सकती है shift

जोड़ा अमान्य विकल्पों के रूप में डैश ( ) से शुरू होने वाले फ़ाइलनाम को पहचानने से --रोकता mvहै -


क्या आपको प्रत्येक मामले में नहीं तोड़ना चाहिए?
आर्चेमर

2
@Archemar: नहीं, कोई फ़ॉल-थ्रू नहीं है (बहुत सारी अन्य भाषाओं के विपरीत)।
Mat

2
अगर आप (ksh, bash, zsh केवल) के ;&बजाय का उपयोग करते हैं, तो @ गिर, वहाँ है ;;। लेकिन फिर breakभी गिरने से नहीं रोकता है, breakकेवल छोरों को तोड़ना है।
स्टीफन चेजलस

यह बहस नहीं है, ifलेकिन [आदेश के लिए है।
स्टीफन चेजलस

1
सुधार: दोहरे उद्धरण केवल बाएं हाथ की ओर की जरूरत नहीं है! [[ $foo == $bar ]]पैटर्न मिलान का प्रदर्शन करेंगे, लेकिन [[ $foo == "$bar" ]]ऐसा नहीं होगा।
nyuszika7h

7

ऐसा क्यों हो रहा है, इस सवाल का जवाब देने के लिए, [उर्फ testका यह व्यवहार POSIX में प्रलेखित है :

निम्नलिखित सूची में, $ 1, $ 2, $ 3 और $ 4 परीक्षण के लिए प्रस्तुत तर्कों का प्रतिनिधित्व करते हैं:

[...]

1 तर्क:

सच से बाहर निकलें (0) यदि $ 1 शून्य नहीं है; अन्यथा, झूठ से बाहर निकलें।

आप इसे 1 तर्क से पारित कर रहे हैं 2=1, जो कि अशक्त नहीं है, और इसलिए testसफलता के साथ बाहर निकलता है।

जैसा कि अन्य पोस्ट (और शेलचेक ) बताते हैं, यदि आप समानता के लिए तुलना करना चाहते हैं, तो आपको इसके बजाय 3 तर्क पारित करने होंगे 2, =और 1


3
एक अर्थ में यह एकमात्र ऐसा उत्तर है जिसने पूछे गए प्रश्न का उत्तर दिया है (एक या एक से अधिक व्यंजनों को देने के बजाय जो ओपी पूरा करना चाहता था), और शेल पर्याप्त रूप से रहस्यमय हो सकता है कि पता है कि यह उन चीजों को क्यों करता है जो यह उपयोगी है ।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली

1

मैं सिर्फ एक पोर्टेबल अभी तक भी neater विकल्प की सिफारिश करना चाहता हूं । बैश सार्वभौमिक नहीं है (और यदि आपको सार्वभौमिक की आवश्यकता नहीं है, तो आप शेल स्क्रिप्ट क्यों लिख रहे हैं?)

#! /bin/sh
action="$1"
shift
case "$action" in
    1) dest=Sun   ;;
    2) dest=Moon  ;;
    3) dest=Earth ;;
    *) echo "Unrecognized action code '$action' (must be 1, 2, or 3)" >&2; exit 1 ;;
esac
mv -- "$@" ~/lab/"$dest"

(बालकों पर ध्यान दें: हाँ, मुझे पता है $actionकि case "$action" inरेखा पर आस-पास के उद्धरण अनावश्यक हैं, लेकिन मुझे लगता है कि उन्हें वैसे भी वहां रखना सबसे अच्छा है, ताकि भविष्य के पाठकों को यह याद न रहे।)


1
"बैश सार्वभौमिक नहीं है (और यदि आपको सार्वभौमिक की आवश्यकता नहीं है, तो आप एक शेल स्क्रिप्ट क्यों लिख रहे हैं?)" - इसका मतलब यह है कि बैश स्क्रिप्टिंग का कोई उपयोग मामलों में नहीं है।
रुस्लान

@Ruslan हाँ, यह मेरी राय है। पोर्टेबल /bin/shस्क्रिप्ट लिखें , अगर आपको इसकी आवश्यकता है; अन्यथा, एक पटकथा भाषा में लिखें जो शेल की तुलना में कम भयानक है। मूल पर्ल दुभाषिया वास्तव में बश की तुलना में विरासत के मालिकाना माहौल और कट-डाउन एम्बेडेड वातावरण में मौजूद होने की अधिक संभावना है।
zwol
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.