যুক্তি ছাড়াই বা ছাড়াই কোনও স্ক্রিপ্ট কীভাবে লিখবেন?


13

আমার কাছে বাশ স্ক্রিপ্ট রয়েছে যা এরকম কিছু হয়:

#!/bin/bash

if [ $1 = "--test" ] || [ $1 = "-t" ]; then
    echo "Testing..."
    testing="y"

else
    testing="n"
    echo "Not testing."

fi

সুতরাং আমি যা করতে সক্ষম হতে চাই তা কেবল এটির সাথে ./script --testবা চালাতে হবে না ./script -tতবে কোনও যুক্তি (ন্যায়বিচার ./script) না দিয়েই চলবে , তবে আপাতদৃষ্টিতে যদি আমি এটি বর্তমান কোড দিয়ে করি তবে আউটপুটটি কেবল:

./script: line 3: [: =: unary operator expected
./script: line 3: [: =: unary operator expected
Not testing.

সুতরাং আমি এটি কীভাবে প্রোগ্রাম করব যাতে কোনও যুক্তি elseছাড়াই এটি চালানো ত্রুটি না ছুঁড়েই করণীয় ? আমি কি ভুল করছি?


1
আপনার চেকগুলির চারপাশে আপনার ডাবল বন্ধনী প্রয়োজন। [[]]
টেরেন্স


@ টেরেন্স আপনার প্রয়োজন নেই, যদিও আপনি বাশকে টার্গেট করেন তবে এগুলি ব্যবহার করা উচিত।
Ruslan

উত্তর:


1

শেল স্ক্রিপ্টিংয়ে দীর্ঘ বিকল্পগুলি ব্যবহারের "যথাযথ উপায়" হ'ল getopt GNU ইউটিলিটি । এর রয়েছে getopts একটি ব্যাশ বিল্ট-ইন যে , কিন্তু এটি শুধুমাত্র মত সংক্ষিপ্ত অপশন দেয় -tgetoptব্যবহারের কয়েকটি উদাহরণ এখানে পাওয়া যাবে

এখানে এমন একটি স্ক্রিপ্ট রয়েছে যা দেখায় যে আমি কীভাবে আপনার প্রশ্নের কাছে যেতে পারি। বেশিরভাগ পদক্ষেপের ব্যাখ্যাটি স্ক্রিপ্টের মধ্যেই মন্তব্য হিসাবে যুক্ত করা হয়।

#!/bin/bash

# GNU getopt allows long options. Letters in -o correspond to
# comma-separated list given in --long.

opts=$(getopt -o t --long test -- "$*")
test $? -ne 0 && exit 2 # error happened

set -- $opts # some would prefer using eval set -- "$opts"
# if theres -- as first argument, the script is called without
# option flags
if [ "$1" = "--"  ]; then
    echo "Not testing"
    testing="n"
    # Here we exit, and avoid ever getting to argument parsing loop
    # A more practical case would be to call a function here
    # that performs for no options case
    exit 1
fi

# Although this question asks only for one 
# option flag, the proper use of getopt is with while loop
# That's why it's done so - to show proper form.
while true; do
    case "$1" in
        # spaces are important in the case definition
        -t | --test ) testing="y"; echo "Testing" ;;
    esac
    # Loop will terminate if there's no more  
    # positional parameters to shift
    shift  || break
done

echo "Out of loop"

কয়েকটি সরলীকরণ এবং সরানো মন্তব্য সহ, এটিকে ঘনীভূত করা যেতে পারে:

#!/bin/bash
opts=$(getopt -o t --long test -- "$*")
test $? -ne 0 && exit 2 # error happened
set -- $opts    
case "$1" in
    -t | --test ) testing="y"; echo "Testing";;
    --) testing="n"; echo "Not testing";;
esac

16

বিভিন্ন পথ; দুটি সবচেয়ে সুস্পষ্ট:

  • $1ডাবল উদ্ধৃতি রাখুন :if [ "$1" = "--test" ]
  • $ # ব্যবহার করে আর্গুমেন্টের সংখ্যা পরীক্ষা করুন

আরও ভাল, getopts ব্যবহার করুন।


2
Getopts ব্যবহারের জন্য +1। এটিই যাওয়ার সেরা উপায়।
শেঠ

3
আর একটি প্রচলিত প্রথা হ'ল [ "x$1" = "x--test" ]কমান্ড-লাইন যুক্তিগুলি রক্ষা করা যা কমান্ডের জন্য বৈধ অপারেটর [। (এটি [[ ]]পছন্দ করার কারণে আরও একটি কারণ : এটি শেল সিনট্যাক্সের অংশ, কেবল একটি বিল্টিন কমান্ড নয়))
পিটার কর্ডেস

7

শর্তের ভিতরে আপনার ভেরিয়েবলগুলি উদ্ধৃত করতে হবে। প্রতিস্থাপন করুন:

if [ $1 = "--test" ] || [ $1 = "-t" ]; then

সঙ্গে:

if [ "$1" = '--test' ] || [ "$1" = '-t' ]; then  

তাহলে এটি কাজ করবে:


Not ~ ./test.sh পরীক্ষা করা হচ্ছে না।

সর্বদা আপনার ভেরিয়েবলগুলি ডাবল উদ্ধৃতি!


একক-কোটগুলি কী প্রয়োজনীয় বা এর পরিবর্তে কেউ ডাবল-কোট ব্যবহার করতে পারে?

সুনির্দিষ্ট উত্তরটি আপনি কোন শেলটি ব্যবহার করছেন তার উপর নির্ভর করে তবে আপনার প্রশ্ন থেকে আমি ধরে নিয়েছি আপনি বোর্ন-শেল বংশধর ব্যবহার করছেন। একক এবং ডাবল উদ্ধৃতিগুলির মধ্যে প্রধান পার্থক্য হ'ল ভেরিয়েবল প্রসারণটি ডাবল কোটের অভ্যন্তরে ঘটে, তবে একক উদ্ধৃতিতে নয়: OO এফইও = বার $ প্রতিধ্বনি "$ এফইও" বার $ প্রতিধ্বনি '$ এফও' $ এফইও (এইচএম .... পারেন ' মন্তব্যে টি ফর্ম্যাট কোড ...)
জেইয়ে

@ পরানয়েডপান্ডা আপনার একক উদ্ধৃতি ব্যবহার করতে হবে না, তবে স্ট্রিং লিটারে এগুলি ব্যবহার করা ভাল অনুশীলন। আপনার স্ট্রিং ডেটাতে একটি প্রতীক বাশ প্রসারিত হতে চাইলে আপনি পরে অবাক হবেন না।
শেঠ

@ পরনয়েড পান্ডা @ জায়ে বলেছেন: একক উদ্ধৃতি সহ আউটপুটে কোনও পরিবর্তনশীল প্রসারণ foo=bar echo '$foo'প্রিন্ট নেই $foo, পরিবর্তে foo=bar echo "$foo"প্রিন্ট রয়েছে bar
ইকনস

4

আপনি বাশ ব্যবহার করছেন। ব্যাশ করার জন্য একটি মহান বিকল্প আছে [: [[। এর সাথে [[, আপনাকে উদ্ধৃতি দেওয়ার বিষয়ে চিন্তা করতে হবে না এবং এর [জন্য যথাযথ সমর্থন সহ আপনি আরও অনেক অপারেটর পাবেন ||:

if [[ $1 = "--test" || $1 = "-t" ]]
then
    echo "Testing..."
    testing="y"
else
    testing="n"
    echo "Not testing."
fi

অথবা আপনি নিয়মিত প্রকাশ করতে পারেন:

if [[ $1 =~ ^(--test|-t) ]]
then
    echo "Testing..."
    testing="y"
else
    testing="n"
    echo "Not testing."
fi

অবশ্যই, যথাযথ উদ্ধৃতি সর্বদা করা উচিত, তবে [ব্যাশ ব্যবহারের সাথে লেগে থাকার কোনও কারণ নেই ।


3

যুক্তি উপস্থিত রয়েছে কিনা তা পরীক্ষা করার জন্য (সাধারণভাবে এবং তদনুসারে ক্রিয়াগুলি করুন) এটি কাজ করা উচিত:

#!/bin/bash

check=$1

if [ -z "$check" ]; then
  echo "no arguments"
else echo "there was an argument"
fi

না কেন [ -z "$1" ]?
ইকনস

@। এই ক্ষেত্রে, অবশ্যই, সাধারণত স্ক্রিপ্টগুলিতে, আমি পরিবর্তনশীলটিকে একবারে কল করি, পদ্ধতিগুলিতে এটি উল্লেখ করি, যা সাধারণত একবারে হয়। নমুনায় প্রোটোকল রাখার সিদ্ধান্ত নিয়েছে।
জ্যাকব ভিলিজম

এই নমুনায় আপনি $checkএকবার ব্যবহার করেছেন বলে মনে হয় shift, যে কোনও এস এর আগে , তাই $1পরিবর্তে এটি ব্যবহার করা ভাল ।
ইকনস

@ ΈρικΚωνσταντόπουλος অবশ্যই উল্লিখিত নয়, এটি স্ক্রিপ্টগুলিতে ব্যবহার করার জন্য একটি নমুনা । স্ক্রিপ্টগুলিতে বার বার একই কাজ করা খারাপ অভ্যাস।
জ্যাকব Vlijm

আপনি কী বলতে চাইছেন তা আমি বুঝতে পেরেছি, তবে #!নমুনা সরবরাহ করার সময় শেবাং ব্যবহার না করা ভাল অনুশীলন (আপনার কোডের বাইরে শেলটি বর্ণনা করা উচিত)।
ইকনস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.