Check REPLY বিভিন্ন সংখ্যার মধ্যে রয়েছে কিনা তা পরীক্ষা করুন


30

আমি লিনাক্সের জন্য শেল স্ক্রিপ্ট লিখছি, ব্যাশ ব্যবহার করে, কোনও ভিডিও-ফাইলকে এমপি 4-তে অনুবাদ করতে। তার জন্য, আমি অডিওর avconvসাথে ব্যবহার করছি libvorbis

আমার স্ক্রিপ্টের ভিতরে, ব্যবহারকারীর জন্য আমার একটি প্রশ্ন রয়েছে:

read -p "- Audio Quality [scale from -2 to 10] ? "
    if [ -n "$REPLY" ] ; then
    ABITRATE="-aq $REPLY"
    fi

আমার "ABITRATE" স্ট্রিংটি চূড়ান্ত avconvকমান্ড-লাইনে চলে যায় ।

তবে আমি ব্যবহারকারীকে কেবি (কিলোবিট) এর একটি মান দিয়ে সেই প্রশ্নের উত্তর দেওয়ার এবং এটি যে স্কেল libvorbisব্যবহার করে তা অনুবাদ করার সুযোগ দিতে চাই । "-২ থেকে 10" স্কেলটি হ'ল:

Quality Kbit/s  Normalization
-----------------------------
 -2      ~32        y
 -1      ~48        y
  0      ~64        y
  1      ~80        y
  2      ~96        y
  3     ~112        y
  4     ~128        n
  5     ~160        n
  6     ~192        n
  7     ~224        n
  8     ~256        n
  9     ~320        n
 10     ~500        n

আমি জানতে চাই কীভাবে আমার $ REPLY সংখ্যাটিতে রয়েছে কিনা তা পরীক্ষা করে দেখুন। উদাহরণস্বরূপ, আমি চাই আমার স্ক্রিপ্টটি এরকম কিছু করুন:

if [ $REPLY is a number between 1 and 32 ] ; then 
 REPLY="-2"
elif [ $REPLY is a number between 33 and 48 ] ; then 
 REPLY="-1"
fi

এটি কি সম্ভব (আমি 'হ্যাঁ অবশ্যই বলতে চাই, কঠিন হওয়া উচিত না' তবে আমি সিনট্যাক্সটি ব্যবহার করতে জানি না)?


আফাইক, ভর্বিস কোনও এমপি 4 ফাইলে কোনও বৈধ অডিও কোডেক নয় (আপনি এএসি বা সম্ভবত এমপি 3 ব্যবহার করতে চান) ...
অশুভ ঘটনা

ধন্যবাদ, এটি ভিএলসিতে ভাল কাজ করেছে তবে টোটেম এটি পড়তে চায় না। আমি libvo_aacenc এ স্যুইচ করছি
মিঃভায়াকাদজি

উত্তর:


30

[কমান্ড / শেল builtin তুলনা পরীক্ষা হয়েছে যাতে আপনি শুধু করতে পারি না

if [ "$REPLY" -ge 1 -a "$REPLY" -le 32 ]; then REPLY=-2;
elif [ "$REPLY" -ge 33 -a "$REPLY" -le 48 ]; then REPLY=-1; fi

যেখানে -geবৃহত্তর বা সমান-সমান (এবং আরও কিছু) এর অর্থ। -aযৌক্তিক "এবং"। [কমান্ড মাত্র একটি কমান্ড, না বিশেষ সিনট্যাক্স (এটা আসলে হিসাবে একই হয় test: খুঁজে বার করো man testতাই এটি পরে স্থান প্রয়োজন,)। আপনি যদি [$REPLYএটি লিখেন তবে নামের একটি কমান্ড খুঁজে পেতে [$REPLYএবং এটি কার্যকর করার চেষ্টা করবে, যা কার্যকর হবে না। একই বন্ধ হয় ]

সম্পাদনা করুন: সংখ্যাটি পূর্ণসংখ্যা হয় কিনা তা পরীক্ষা করতে (যদি তা আপনার কোডটিতে ঘটতে পারে), প্রথমে পরীক্ষাটি করুন

if [[ "$REPLY" =~ ^[0-9]+$ ]]; then
   existing code
else echo "$REPLY is not an integer" >&2 && exit 1; fi

অবশ্যই এই সমস্ত বন্ধনী এক্সপ্রেশন 0 (সত্য) বা 1 (মিথ্যা) প্রত্যাবর্তন করে এবং একত্রিত হতে পারে। আপনি কেবল একই ব্র্যাকেটে সমস্ত কিছু রাখতে পারবেন না, আপনি এটি করতেও পারেন

if [[ "$REPLY" =~ ^[0-9]+$ ]] && [ "$REPLY" -ge 1 -a "$REPLY" -le 32 ]; then ...

বা অনুরূপ কিছু।


ঠিক আমি যা খুঁজছিলাম, ধন্যবাদ! আমি কি পরিবর্তে সহজ তুলনা এক্সপ্রেশন ব্যবহার করতে পারি >=?
মিঃ ভাইকাদজি

বাশ পরীক্ষার জন্য বহু ধরণের বন্ধনীর অনুমতি দেয়। আপনার কাছে এই traditional [তিহ্যবাহী বন্ধনী রয়েছে, যা এখানে দেখা হিসাবে কাজ করে man test। এগুলি traditionalতিহ্যবাহী এবং বোকা-প্রমাণ। তারপরে, আপনার কাছে প্রচুর বাশ বিল্টিন রয়েছে। আপনার মত [[যা একই, তবে একেবারে একই নয়, কারণ এটি কোনও পথের নামগুলি প্রসারিত করে না (সেখানে <<> মানে স্ট্রিং তুলনা, এবং পূর্ণসংখ্যার তুলনাগুলি একই [)) উভয়েরই ফাইল অস্তিত্ব, অনুমতি ইত্যাদির জন্য প্রচুর পরীক্ষাও রয়েছে। তারপরে আপনি @ ডিভনুলের উত্তরে একক (এবং দ্বিগুণ ((ব্যবহার করেছেন। man bashঅধীনে চেক আউট Compound Commands
প্রাচ্য

1
@ মিঃভায়াকাদজি আমি আপনাকে ভেরিয়েবলটি একটি সংখ্যা কিনা তা পরীক্ষা করে দেখার জন্য আমি উচ্চ প্রস্তাব দিচ্ছি, অন্যথায় আপনি অপ্রত্যাশিত ফলাফল পেতে পারেন:foo='a'; [[ "$foo" -lt 32 ]] && echo yes
টেরডন

12

আপনি কেবল বলতে পারেন:

((REPLY>=1 && REPLY<=32)) && REPLY=-2
((REPLY>=33 && REPLY<=48)) && REPLY=-1

ম্যানুয়াল থেকে উদ্ধৃতি :

((...))

(( expression ))

গাণিতিক এক্সপ্রেশনটি নীচে বর্ণিত বিধি অনুসারে মূল্যায়ন করা হয় ( শেল অ্যারিমেটিক দেখুন )। যদি অভিব্যক্তির মান শূন্য হয় না, তবে ফেরতের স্থিতি 0 হয়; অন্যথায় রিটার্নের স্থিতি ১। এটি হ'ল সমান equivalent

let "expression"

আমি সরলতা পছন্দ, কিন্তু কি ((? আমি এগুলিকে প্রম্পটে ব্যবহার করার চেষ্টা করেছি এবং এটি মনে হয় এটির মতো কাজ করে if [ ] ; thenতবে আমি জানি না যে এটি বিদ্যমান।
মিঃ ভাইকাদজি

@ মিঃভায়াকাদজি ম্যানুয়াল থেকে একটি রেফারেন্স যুক্ত করেছেন। এটি পরিষ্কার না হলে আমাকে জানান।
ডেভনুল

1
@ মিঃভায়াকাদজি তদ্ব্যতীত, বক্তব্য if [ condition ]; then foo; fiবলা সমান condition && foo
ডেভনুল

ঠিক আছে চমৎকার ! আমি যদি পারতাম তবে আপনার উভয় asers (orion এবং আপনি) উভয়কেই আমি গ্রহণ করতে চাই। এই সমস্ত জন্য অনেক অনেক ধন্যবাদ, আমি অনেক শিখেছি।
মিঃ ভাইকাদজি

আপনি যদি এটি ব্যবহার করেন তবে আপনি নেতৃস্থানীয় শূন্যগুলি ফেলা করতে চাইতে পারেন। a=08; (( a > 1 ))08 থেকে অষ্টাল হিসাবে বিবেচিত ত্রুটি হবে will আপনি দশমিক সঙ্গে জোর করতে পারে 10#$REPLYcmd && cmdপুরোপুরি একই হিসাবে নয় if cmd; then ...একবার আপনি একটি প্রয়োজন elseঅংশ, লজিক্যাল chaining &&এবং ||সূক্ষ্ম বাগ হতে পারে।
llua

4

আপনি এরকম কিছু করতে পারেন:

#!/usr/bin/env bash
read -p "- Audio Quality [scale from -2 to 10] ? "
if [ -n "$REPLY" ] ; then
    ABITRATE="-aq $REPLY"
fi

echo "You chose : $ABITRATE : $REPLY"
## If 0 < $REPLY < 33 and $REPLY is a number
if [[ "$REPLY" -gt 0 && "$REPLY" -lt 33 && "$REPLY" =~ '^[0-9]$' ]]
then
    echo "GOOD"
else
    echo "BAD"
fi

2

প্রথমে পরীক্ষা করুন যে ইনপুটটি সংখ্যাযুক্ত কিনা is উদাহরণস্বরূপ, বাশ শর্তসাপেক্ষ এক্সপ্রেশনগুলির নিয়মিত এক্সপ্রেশন ম্যাচ অপারেটর ব্যবহার করুন :

if [[ $REPLY =~ -?[0-9]+ ]]; then
  echo "Invalid input (not numeric): $REPLY"
  exit 2
fi

সংখ্যার ব্যাপ্তি পরীক্ষা করতে আপনার দুটি সম্ভাবনা রয়েছে:

  • -gtএর অপারেটর শর্তাধীন অভিব্যক্তি ভিতরে [ … ]বা [[ … ]](হুঁশিয়ার করে <এবং >অপারেটরদের স্ট্রিং তুলনা করি, না সাংখ্যিক মান তুলনা, তাই [[ 10 < 9 ]]সত্য);
  • ভিতরে স্বাভাবিক গাণিতিক অপারেটরগুলি ((…))

এভাবে:

if ((REPLY >= -2 && REPLY <= 10)); then
  : # do nothing -- pass directly to libvorbis
elif ((REPLY <= 24)); then
  echo "Value outside supported range: $REPLY"
  exit 2
elif ((REPLY <= 135)); then
  REPLY=$(((REPLY+8) / 16 - 4))
elif ((REPLY <= 271)); then
  REPLY=$(((REPLY+16) / 32))
elif ((REPLY <= 400)); then
  REPLY=9
elif ((REPLY <= 707)); then
  REPLY=10
else
  echo "Value outside supported range: $REPLY"
  exit 2
fi

(আপনি বিভিন্ন আনুমানিক বিধি ব্যবহার করতে চাইতে পারেন, আমি যেগুলি বেছে নিয়েছি সেগুলি এখানে সেরা কিনা তা আমি জানি না))


1

কোনও স্ট্রিং একটি (দশমিক) সংখ্যা কিনা তা সঠিকভাবে সনাক্ত করতে আমাদের প্রথমে দশমিক পূর্ণসংখ্যার সংখ্যাটি কী তা নির্ধারণ করতে হবে। একটি সহজ এবং এখনও সম্পূর্ণ সংজ্ঞা:

Optionচ্ছিক চিহ্নের ক্রম (+ বা -) এর পরে 18 (দশমিক) বেশি নয়।

এবং এই পদক্ষেপগুলি প্রয়োজন:

  1. দশমিক অঙ্ক নয় এমন সমস্ত অক্ষর মুছে ফেলুন (চিহ্নের পরে)।
  2. সমস্ত leadingচ্ছিক নেতৃস্থানীয় শূন্যগুলি সরান। শীর্ষস্থানীয় শূন্যগুলি শেলটি বিশ্বাস করবে যে এই সংখ্যাটি অষ্টালে রয়েছে।
  3. পূর্ণসংখ্যার সর্বাধিক আকার 18 টি সংখ্যায় সীমাবদ্ধ করুন। 2 ** 63-1 এর নীচে (সর্বোচ্চ 64 বিট পূর্ণসংখ্যার)।

কেবলমাত্র একটি রেজেক্স তার বেশিরভাগটি করবে:

re='^([+-])?0*([0-9]{1,18})$'
[[ $number =~ $re ]] && integer=${BASH_REMATCH[*]:1}

বেশ কয়েকটি সংখ্যার প্রক্রিয়া করার কোডটি হ'ল:

#!/bin/bash
DebugLevel=4     # 1:fatal 2:error 3:warn 4:info 5:debug 6:trace

SayMsg    (){   local a; a=$1; shift ;            # Log level
                [[ $a -le $DebugLevel ]] && printf '%s' "$@" $'\n' >&2 ;
            }
SayError  (){   a=$1; shift; printf '%s' "$@" $'\n' >&2; exit   "$a";   }

parseint  (){   local re # Parse the first argument as an integer or fail
                re='^([+-])?0*([0-9]{1,18})$'
                [[ $1 =~ $re ]] || { SayMsg 4 "Invalid number $1"; return 2; }
                integer=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
                echo "integer=$integer"
             }

while read val; do
    parseint "$val"
    done <<-\_EOT_
    0
    1
    10
    100
    2345
    123456789012345678
    923456789012345678
    999999999999999999
    0000000012345
    +023
    -00045
    -76
    ""
    ''
    a
    abc
    1234567890123456789
    7.23
    -8.17
    1e3
    10+11
    _EOT_

যা মুদ্রণ করবে:

integer=0
integer=1
integer=10
integer=100
integer=2345
integer=123456789012345678
integer=923456789012345678
integer=999999999999999999
integer=12345
integer=+23
integer=-45
integer=-76
Invalid number ""
Invalid number ''
Invalid number 
Invalid number a
Invalid number abc
Invalid number 1234567890123456789
Invalid number 7.23
Invalid number -8.17
Invalid number 1e3
Invalid number 10+11

একবার নম্বরটি পরিষ্কার এবং পরিষ্কার হয়ে গেলে, একমাত্র অনুপস্থিত পরীক্ষাটি হ'ল মানের সীমাটি সীমাবদ্ধ করে। এই সাধারণ লাইনগুলি এটি করবে:

(( 1  <= integer && integer <= 32 )) && REPLY="-2"
(( 33 <= integer && integer <= 48 )) && REPLY="-1"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.