ব্যাশে ভেরিয়েবলের সংখ্যা থাকলে আমি কীভাবে পরীক্ষা করব?


596

আমি ঠিক কীভাবে বুঝতে পারি না যে আমার স্ক্রিপ্টে একটি আর্গুমেন্ট একটি নম্বর আছে কিনা তা আমি নিশ্চিত করব।

আমি যা করতে চাই তা হ'ল কিছু:

test *isnumber* $1 && VAR=$1 || echo "need a number"

কোন সাহায্য?


17
সরাইয়া হিসাবে - test && echo "foo" && exit 0 || echo "bar" && exit 1আপনি যে পদ্ধতির ব্যবহার করছেন তাতে কিছু অনিচ্ছাকৃত পার্শ্ব প্রতিক্রিয়া থাকতে পারে - যদি প্রতিধ্বনি ব্যর্থ হয় (সম্ভবত আউটপুটটি একটি বন্ধ এফডি হয়), তবে exit 0এই কোডটি বাদ দেওয়া হবে এবং কোডটি পরে চেষ্টা করবে echo "bar"। এটিও যদি এটি ব্যর্থ হয় তবে &&শর্তটি ব্যর্থ হবে এবং এটি কার্যকর হবে না exit 1! ifপরিবর্তে &&/ প্রকৃত বিবৃতি ব্যবহার ||অপ্রত্যাশিত পার্শ্ব প্রতিক্রিয়াগুলির ঝুঁকির কম।
চার্লস ডাফি

@ চার্লসডুফি এটাই সত্যিকারের চালাক চিন্তাভাবনা যা বেশিরভাগ মানুষ কেবল তখনই পায় যখন লোমশ বাগগুলি খুঁজে বের করতে হয় ...! আমি কখনও ভাবিনি যে প্রতিধ্বনি ব্যর্থতা ফিরে আসতে পারে।
ক্যামিলো মার্টিন

6
পার্টিতে দেরি হয়ে গেলেও, কিন্তু চার্লস যে বিপদগুলি নিয়ে লিখেছিলেন সেগুলি সম্পর্কে আমি জানি, কারণ বেশ কিছুদিন আগেও আমাকে তাদের মধ্য দিয়ে যেতে হয়েছিল। সুতরাং আপনার জন্য এখানে একটি 100% বোকা-প্রমাণ (এবং ভালভাবে পঠনযোগ্য) লাইন রয়েছে: [[ $1 =~ "^[0-9]+$" ]] && { echo "number"; exit 0; } || { echo "not a number"; exit 1; }কোঁকড়া বন্ধনীগুলি নির্দেশ করে যে জিনিসগুলি একটি সাবশেলে চালিত করা উচিত নয় (যা অবশ্যই ()প্যারেন্টেসিসের পরিবর্তে ব্যবহৃত হবে)। ক্যাভেট: চূড়ান্ত সেমিকোলনটি কখনই মিস করবেন না । অন্যথায় আপনি bash
কুরুচিপূর্ণ

5
উবুন্টুতে এটি কাজ করে না, যদি না আপনি উদ্ধৃতিগুলি না সরিয়ে থাকেন। সুতরাং এটি ঠিক হওয়া উচিত[[ 12345 =~ ^[0-9]+$ ]] && echo OKKK || echo NOOO
ট্রেভিও

4
"সংখ্যা" বলতে কী বোঝাতে চাইছেন সে সম্পর্কে আপনাকে আরও সুনির্দিষ্ট হতে হবে । একটি পূর্ণসংখ্যা? একটি নির্দিষ্ট পয়েন্ট নম্বর? বৈজ্ঞানিক ("ই") স্বরলিপি? প্রয়োজনীয় রেঞ্জ (যেমন একটি 64৪-বিট স্বাক্ষরবিহীন মান) রয়েছে, বা আপনি কোনও সংখ্যা লিখতে পারবেন কি?
টবি স্পিড

উত্তর:


801

একটি পদ্ধতির নিয়মিত এক্সপ্রেশন ব্যবহার করা যেমন:

re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
   echo "error: Not a number" >&2; exit 1
fi

মানটি অগত্যা যদি পূর্ণসংখ্যার হয় না, তবে যথাযথভাবে রেজেক্স সংশোধন করার কথা বিবেচনা করুন; এই ক্ষেত্রে:

^[0-9]+([.][0-9]+)?$

... বা, একটি চিহ্ন সহ সংখ্যাগুলি পরিচালনা করতে:

^[+-]?[0-9]+([.][0-9]+)?$

7
এই পদ্ধতির জন্য +1 করুন, তবে দশমিকের সাথে যত্ন নিন, উদাহরণস্বরূপ, "1.0" বা "1,0" প্রিন্ট "ত্রুটি: একটি সংখ্যা নয়" দিয়ে এই পরীক্ষাটি করুন।
সোর্সবেলগুলি

15
আমি '' এক্সিকিউট> & 2; প্রতিধ্বনি ... '' বরং মূর্খ। স্রেফ '' প্রতিধ্বনি ...> & 2 ''
lhunath

5
@ আপনি কি সত্যিই একাধিক বিয়োগ চিহ্ন পরিচালনা করতে চান? আমি এটা করতে চাই ^-?বদলে ^-*যদি না আপনি আসলে সঠিকভাবে একাধিক inversions হ্যান্ডেল করতে কাজ করছেন।
চার্লস ডাফি

4
@ স্যান্ড্রাশ্লাইচিংটি ভবিষ্যতের সমস্ত আউটপুট স্ট্যাডারে চলে যায়। এখানে এটির সত্যিকার অর্থে কোনও বিন্দু নয়, যেখানে কেবল একটি প্রতিধ্বনি রয়েছে, তবে ত্রুটি বার্তাগুলি একাধিক লাইনে বিস্তৃত ক্ষেত্রে আমি এটির অভ্যাসের অভ্যাস করি।
চার্লস ডাফি

29
আমি নিশ্চিত না কেন নিয়মিত এক্সপ্রেশনটি একটি ভেরিয়েবলে সংরক্ষণ করতে হবে তবে এটি যদি সামঞ্জস্যের জন্য হয় তবে আমি এটি প্রয়োজনীয় মনে করি না। আপনি শুধু সরাসরি অভিব্যক্তি প্রয়োগ হতে পারে: [[ $yournumber =~ ^[0-9]+$ ]]
কনসোলবক্স

282

বাশিজম ছাড়াই (এমনকি সিস্টেম ভি sh তেও কাজ করে),

case $string in
    ''|*[!0-9]*) echo bad ;;
    *) echo good ;;
esac

এটি খালি স্ট্রিংগুলি এবং অ-সংখ্যাযুক্ত স্ট্রিংগুলিকে প্রত্যাখ্যান করে, সমস্ত কিছু গ্রহণ করে।

নেতিবাচক বা ভাসমান-পয়েন্ট সংখ্যাগুলির জন্য কিছু অতিরিক্ত কাজ প্রয়োজন। একটি ধারণা বাদ দেওয়া হয়-. প্রথম "খারাপ" প্যাটার্নটি / এতে এবং এর অনুপযুক্ত ব্যবহারগুলিতে আরও "খারাপ" নিদর্শন যুক্ত করা (?*-* / *.*.*)


20
+1 - এটি মূল বোর্ন শেলটির ফিরে যাওয়ার মতো মূর্তিযুক্ত, বহনযোগ্য উপায় এবং গ্লোব স্টাইলের ওয়াইল্ডকার্ডগুলির জন্য অন্তর্নির্মিত সমর্থন করেছে। আপনি যদি অন্য একটি প্রোগ্রামিং ভাষা থেকে এসে থাকেন, তবে তা দেখতে ভীতু মনে হয়, তবে বিভিন্ন উদ্ধৃতি ইস্যু এবং অবিরাম পিছনে / পাশের দিকের সামঞ্জস্য সমস্যার সাথে if test ...
দ্বিধাহীনতা

6
${string#-}নেতিবাচক পূর্ণসংখ্যাকে গ্রহণ করতে আপনি প্রথম লাইনটি (যা এন্টিক বোর্ন শেলগুলিতে কাজ করে না তবে কোনও পসিক্স শেলের মধ্যে কাজ করে) এ পরিবর্তন করতে পারেন।
গিলস 'তাই খারাপ হওয়া বন্ধ করুন'

4
এছাড়াও, এটি ভাসমানের মধ্যে প্রসারিত করা সহজ - কেবল '.' | *.*.*অস্বীকৃত নিদর্শনগুলিতে যুক্ত করুন, এবং অনুমোদিত অক্ষরগুলিতে বিন্দু যুক্ত করুন। একইভাবে, আপনি আগে একটি signচ্ছিক সাইনকে অনুমতি দিতে পারেন, তবে তারপরে আমি case ${string#[-+]}কেবল সাইনটি উপেক্ষা করতে পছন্দ করি ।
ট্রিপলি

স্বাক্ষরিত পূর্ণসংখ্যাগুলি পরিচালনা করার জন্য এটি দেখুন: stackoverflow.com/a/18620446/2013911
নিক্লাস পিটার

2
@ ডোর উক্তিগুলির প্রয়োজন নেই, যেহেতু কেস কমান্ড যেভাবেই শব্দটিতে শব্দ বিভাজন এবং পথের নাম তৈরি করে না। (তবে, ক্ষেত্রে নিদর্শনগুলির
প্রসারকে

193

নীচের সমাধানটি নিয়মিত প্রকাশের প্রয়োজন ছাড়াই বোর্নের মতো মৌলিক শেলগুলিতেও ব্যবহার করা যেতে পারে। মূলত নন-সংখ্যা ব্যবহার করে যে কোনও সংখ্যার মান মূল্যায়ন অপারেশনগুলির ফলে ত্রুটির ফলস্বরূপ শেলটিতে মিথ্যা হিসাবে বিবেচিত হবে:

"$var" -eq "$var"

যেমন হিসাবে:

#!/bin/bash

var=a

if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
  echo number
else
  echo not a number
fi

আপনি $ জন্য পরীক্ষা করতে পারেন? অপারেশনের রিটার্ন কোড যা আরও স্পষ্ট:

[ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null
if [ $? -ne 0 ]; then
   echo $var is not number
fi

"সংখ্যার পূর্ণ প্রত্যাশা প্রত্যাশা করা" বার্তাটি লুকানোর জন্য স্ট্যান্ডার্ড ত্রুটির পুনর্নির্দেশ রয়েছে যা আমাদের কাছে নম্বর না থাকলে বাশ প্রিন্ট করে।

ক্যাভেটস (নীচের মন্তব্যে ধন্যবাদ):

  • দশমিক পয়েন্ট সহ নম্বর নয় নম্বরগুলি বৈধ "সংখ্যা" হিসাবে চিহ্নিত করা যায়
  • [[ ]]পরিবর্তে ব্যবহার করা [ ]সর্বদা মূল্যায়ন করবেtrue
  • বেশিরভাগ নন-বাশ শেল সর্বদা এই অভিব্যক্তিটিকে মূল্যায়ন করবে true
  • বাশের আচরণটি অননুমোদিত এবং সুতরাং সতর্কতা ছাড়াই পরিবর্তিত হতে পারে
  • যদি মানটির পরে শূন্যস্থান অন্তর্ভুক্ত থাকে (যেমন "1 এ") ত্রুটি তৈরি করে, যেমন bash: [[: 1 a: syntax error in expression (error token is "a")
  • মানটি ভেরি-নাম (যেমন i = "i") এর সমান হলে ত্রুটি তৈরি করে, যেমন bash: [[: i: expression recursion level exceeded (error token is "i")

8
আমি এখনও এটির সুপারিশ করব (তবে ভেরিয়েবলগুলি খালি স্ট্রিংয়ের অনুমতি দেওয়ার জন্য উদ্ধৃত করা হবে), যেহেতু ফলাফলটি গ্যাশান হিসাবে বাশের একটি সংখ্যা হিসাবে ব্যবহারযোগ্য হবে , তা যাই হোক না কেন।
l0b0

21
একক বন্ধনী ব্যবহার করার জন্য যত্ন নিন; [[ a -eq a ]]সত্যকে মূল্যায়ন করে (উভয় যুক্তি শূন্যে রূপান্তরিত হয়)
Tgr

3
খুব সুন্দর! নোট করুন এটি কেবল কোনও সংখ্যার জন্য নয়, পূর্ণসংখ্যার জন্য কাজ করে। আমি একটি একক যুক্তি যা একটি পূর্ণসংখ্যার হতে হবে তা যাচাই করা দরকার, সুতরাং এটি ভালভাবে কাজ করেছে:if ! [ $# -eq 1 -o "$1" -eq "$1" ] 2>/dev/null; then
হরিদসভ

6
আমি এই পদ্ধতির বিরুদ্ধে দৃ strongly়ভাবে পরামর্শ দেব কারণ [বিল্টিনগুলি গাণিতিক হিসাবে আর্গুমেন্টগুলি মূল্যায়ন করবে এমন শাঁসের তাত্পর্যপূর্ণ সংখ্যা নয় । এটি ksh93 এবং mksh উভয় ক্ষেত্রেই সত্য। তদ্ব্যতীত, এই উভয় সমর্থন অ্যারে, কোড ইনজেকশন জন্য সহজ সুযোগ আছে। পরিবর্তে একটি প্যাটার্ন ম্যাচ ব্যবহার করুন।
ormaaj

3
আলবার্তোজ্যাকাগনি, বর্তমান ব্যাশের বর্তমান প্রকাশে, এই মানগুলি সংখ্যাসঙ্গিক-প্রসঙ্গের নিয়মের সাথে কেবল ততটা [[ ]]নয় তবে ব্যাখ্যা করা হয় [ ]। এটি বলেছিল, বাশের testনিজস্ব ডকুমেন্টেশনের জন্য এবং পসিক্স স্ট্যান্ডার্ড উভয় দ্বারা এই আচরণটি অনির্ধারিত ; ভবিষ্যতের সংস্করণের বাশ কোনও ডকুমেন্টেড আচরণগত প্রতিশ্রুতি ভঙ্গ না করে ksh সাথে মেলে আচরণকে পরিবর্তন করতে পারে, সুতরাং এর বর্তমান আচরণের উপর নির্ভর করা নিরাপদ থাকার গ্যারান্টিযুক্ত নয়।
চার্লস ডাফি

43

এই সংখ্যাটি যদি কোনও সংখ্যক অ-নেতিবাচক পূর্ণসংখ্যা হয় এবং উভয় শেল স্বতন্ত্র হয় (যেমন বাশিজম ব্যতীত) এবং কেবল শেল বিল্ট-ইনগুলি ব্যবহার করে তবে এটি পরীক্ষা করে:

ত্রুটিপূর্ণ.

যেহেতু এই প্রথম উত্তরটি (নীচে) তাদের অক্ষরের সাথে পূর্ণসংখ্যার জন্য অনুমতি দেয় যতক্ষণ না ভেরিয়েবলের মধ্যে প্রথমটি প্রথম নয়।

[ -z "${num##[0-9]*}" ] && echo "is a number" || echo "is not a number";

সঠিক

হিসাবে jilles মন্তব্য এবং পরামর্শ তার উত্তর এই শেল-নিদর্শন ব্যবহার করে এটি করার সঠিক উপায়।

[ ! -z "${num##*[!0-9]*}" ] && echo "is a number" || echo "is not a number";

5
এটি সঠিকভাবে কাজ করে না, এটি কোনও অঙ্ক দিয়ে শুরু করে যে কোনও স্ট্রিং গ্রহণ করে। মনে রাখবেন যে ORD। VAR ## WORD in এবং এর অনুরূপ ওয়ার্ড একটি শেল প্যাটার্ন, নিয়মিত প্রকাশ নয়।
জিলিস

2
অনুগ্রহ করে আপনি কি এই অভিব্যক্তিটি ইংরেজিতে অনুবাদ করতে পারেন? আমি সত্যিই এটি ব্যবহার করতে চাই, তবে ব্যাশ ম্যান পৃষ্ঠাটি ব্যবহার করার পরেও এটি বিশ্বাস করার পক্ষে আমি এটি যথেষ্ট বুঝতে পারি না।
সিভিফ্যান

2
*[!0-9]*এমন একটি প্যাটার্ন যা কমপক্ষে 1 অ-অঙ্কের অক্ষরের সাথে সমস্ত স্ট্রিংয়ের সাথে মেলে। ${num##*[!0-9]*}এটি একটি "প্যারামিটার এক্সপেনশন" যেখানে আমরা numভেরিয়েবলের সামগ্রী নিয়ে থাকি এবং প্যাটার্নের সাথে মেলে এমন দীর্ঘতম স্ট্রিংটি সরিয়ে ফেলি। যদি প্যারামিটার সম্প্রসারণের ফলাফলটি খালি না হয় ( ! [ -z ${...} ]) তবে এটি কোনও সংখ্যা, কারণ এতে কোনও অ-অঙ্কের অক্ষর নেই।
মুর্চি

দুর্ভাগ্যক্রমে এটি ব্যর্থ হয় যদি আর্গুমেন্টে কোনও সংখ্যা থাকে তবে তা বৈধ সংখ্যা না হলেও। উদাহরণস্বরূপ "exam1ple" বা "a2b"।
স্টাডিজিক 6:59

দু'জনেই ব্যর্থ122s :-(
হস্তুর

40

কেউ বাশের বর্ধিত প্যাটার্ন মেলানোর পরামর্শ দেয়নি :

[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"

5
গ্লেন, আমি shopt -s extglobআপনার পোস্ট থেকে সরিয়ে দিচ্ছি (যেটি আমি উজ্জীবিত করেছি, এটি আমার প্রিয় উত্তরগুলির মধ্যে একটি), যেহেতু শর্তাধীন কনস্ট্রাক্টসে আপনি পড়তে পারেন: যখন ==এবং !=অপারেটরগুলি ব্যবহার করা হয়, তখন অপারেটরের ডানদিকে স্ট্রিংটিকে একটি নিদর্শন হিসাবে বিবেচনা করা হয় এবং এটি ম্যাচ করা হয় নিয়ম অনুযায়ী এ নীচে বর্ণিত প্যাটার্ন ম্যাচিং , যদি extglobশেল বিকল্পটি সক্ষম হয়। আমি আশা করি আপনি কিছু মনে করবেন না!
gniourf_gniourf

এই জাতীয় প্রসঙ্গে, আপনার দরকার নেই shopt extglob... এটি জানা ভাল জিনিস!
gniourf_gniourf

সাধারণ পূর্ণসংখ্যার জন্য ভাল কাজ করে।

2
@ জ্যামেডিয়ান: আপনি ঠিক বলেছেন, এটি বাশ ৪.১ এ যুক্ত করা হয়েছিল (যা ২০০৯ এর শেষে প্রকাশিত হয়েছিল ... ২০০ Bash সালে বাশ ৩.২ প্রকাশিত হয়েছিল ... এটি এখন একটি প্রাচীন সফ্টওয়্যার, যারা অতীতে আটকে রয়েছে তাদের জন্য দুঃখিত)। এছাড়াও, আপনি যুক্তি দিতে পারেন যে এক্সটগ্লোবগুলি যেখানে 2.02 সংস্করণে প্রবর্তিত হয়েছিল (1998 সালে প্রকাশিত), এবং <2.02 সংস্করণে কাজ করবেন না ... এখন এখানে আপনার মন্তব্যটি পুরানো সংস্করণ সম্পর্কিত একটি সতর্কতামূলক হিসাবে কাজ করবে।
gniourf_gniourf

1
এর মধ্যে [[...]]চলকগুলি শব্দ বিভাজন বা গ্লোব সম্প্রসারণের বিষয় নয়।
গ্লেন জ্যাকম্যান 14:25

26

আমি শেলটিতে সরাসরি সংখ্যার ফর্ম্যাটগুলি পার্সিংয়ের সমাধানগুলিতে অবাক হয়েছি। ফাইল এবং প্রক্রিয়াগুলি নিয়ন্ত্রণের জন্য ডিএসএল হওয়ায় শেলটি এটির পক্ষে উপযুক্ত নয়। সামান্য নিচে যথেষ্ট সংখ্যক পার্সার রয়েছে, উদাহরণস্বরূপ:

isdecimal() {
  # filter octal/hex/ord()
  num=$(printf '%s' "$1" | sed "s/^0*\([1-9]\)/\1/; s/'/^/")

  test "$num" && printf '%f' "$num" >/dev/null 2>&1
}

আপনার প্রয়োজনীয় নির্দিষ্ট বিন্যাসে '% f' পরিবর্তন করুন।


4
isnumber(){ printf '%f' "$1" &>/dev/null && echo "this is a number" || echo "not a number"; }
গিলস কুইনট

4
@ স্পটনিক আপনার সংস্করণটি মূল ফাংশনের অন্তর্নিহিত (এবং দরকারী) রিটার্ন মান শব্দার্থকে ভঙ্গ করে। সুতরাং, পরিবর্তে, কেবল ফাংশনটি যেমন রয়েছে তেমন ছেড়ে দিন এবং এটি ব্যবহার করুন:isnumber 23 && echo "this is a number" || echo "not a number"
মাইকেল 25

4
এটিও না হওয়া উচিত 2>/dev/null, যাতে isnumber "foo"স্টাডার দূষণ করে না?
জিওলি

4
বাশের মতো আধুনিক শাঁসকে "ফাইল এবং প্রক্রিয়া নিয়ন্ত্রণের জন্য একটি ডিএসএল" বলা হচ্ছে এগুলি উপেক্ষা করা হচ্ছে যে তারা এর চেয়ে অনেক বেশি ব্যবহৃত হয় - কিছু ডিস্ট্রোরা এতে সম্পূর্ণ প্যাকেজ ম্যানেজার এবং ওয়েব ইন্টারফেসগুলি তৈরি করে (যতটা কুৎসিত হতে পারে)) ব্যাচের ফাইলগুলি আপনার বর্ণনার সাথে মাপসই হয়, এমনকি একটি ভেরিয়েবল সেট করাও কঠিন।
ক্যামিলো মার্টিন

7
এটি মজার বিষয় যে আপনি অন্য ভাষা থেকে কিছু আইডিয়ম অনুলিপি করে স্মার্ট হওয়ার চেষ্টা করছেন। দুর্ভাগ্যক্রমে এটি শেলগুলিতে কাজ করে না। শেলগুলি খুব বিশেষ এবং এগুলি সম্পর্কে দৃ knowledge় জ্ঞান না থাকলে আপনি সম্ভবত ভাঙা কোড লিখেছেন। আপনার কোডটি নষ্ট হয়েছে: isnumber "'a"সত্য ফিরে আসবে। এই নথিভুক্ত করা POSIX বৈশিষ্ট তুমি কিসে পড় করব: প্রধান চরিত্রের একটি একক উদ্ধৃতি বা ডাবল উদ্ধৃতি হয়, তাহলে মান একক উদ্ধৃতি বা ডাবল উদ্ধৃতি নিম্নলিখিত চরিত্রের অন্তর্নিহিত codeset এর সাংখ্যিক মান হইবে ।
gniourf_gniourf

16

আমি উত্তরগুলি খুঁজছিলাম এবং ... বুঝতে পেরেছিলাম যে কেউ ফ্লোট নম্বর (বিন্দু সহ) সম্পর্কে ভাবেনি!

গ্রেপ ব্যবহার করাও দুর্দান্ত।
-E মানে বর্ধিত রেজিএক্সএক্স-
কি মানে নিঃশব্দ (প্রতিধ্বনিত হয় না)
-কিউই উভয়ের সংমিশ্রণ।

কমান্ড লাইনে সরাসরি পরীক্ষা করতে:

$ echo "32" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is: 32

$ echo "3a2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is empty (false)

$ echo ".5" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer .5

$ echo "3.2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is 3.2

ব্যাশ স্ক্রিপ্টে ব্যবহার করা:

check=`echo "$1" | grep -E ^\-?[0-9]*\.?[0-9]+$`

if [ "$check" != '' ]; then    
  # it IS numeric
  echo "Yeap!"
else
  # it is NOT numeric.
  echo "nooop"
fi

JUST পূর্ণসংখ্যার সাথে মিল রাখতে, এটি ব্যবহার করুন:

# change check line to:
check=`echo "$1" | grep -E ^\-?[0-9]+$`

ট্রিপল_আর এবং ট্রিপলির মাধ্যমে ভাসা ব্যবহার সহ সমাধানগুলি ভাসমানগুলির সাথে কাজ করে।
কেন জ্যাকসন

এই এবং খুব ভাল পয়েন্ট জন্য ধন্যবাদ! প্রশ্নটি আসলে এটি হল যে এটি কেবল একটি সংখ্যার নয় কি না তা পরীক্ষা করে নেওয়া যায় ।
তানাসিস

আমি আপনাকেও ধন্যবাদ তনাসিস! আসুন একে অপরকে সর্বদা সহায়তা করি।
সেরজিও অ্যাব্রেউ

12

@ মাইরির কাছে কেবল একটি ফলোআপ। তবে আমার কাছে যথেষ্ট প্রতিনিধি নেই বলে এই পোস্টে মন্তব্য হিসাবে এটি পোস্ট করতে পারেনি। যাইহোক, এখানে আমি ব্যবহার করেছি:

isnum() { awk -v a="$1" 'BEGIN {print (a == a + 0)}'; }

আর্গুমেন্ট সংখ্যা হলে ফাংশন "1" ফিরিয়ে দেবে, অন্যথায় "0" ফিরিয়ে দেবে। এটি পূর্ণসংখ্যার পাশাপাশি ভাসমানদের জন্যও কাজ করে। ব্যবহার এমন কিছু:

n=-2.05e+07
res=`isnum "$n"`
if [ "$res" == "1" ]; then
     echo "$n is a number"
else
     echo "$n is not a number"
fi

4
একটি প্রিন্ট কোড নির্ধারণের চেয়ে একটি সংখ্যা মুদ্রণ কম দরকারী। 'BEGIN { exit(1-(a==a+0)) }'grok থেকে সামান্য কঠিন কিন্তু একটি ফাংশন যা সত্য বা শুধু মত মিথ্যা ফেরৎ ব্যবহার করা যেতে পারে [, grep -qইত্যাদি
tripleee

9
test -z "${i//[0-9]}" && echo digits || echo no no no

${i//[0-9]}$iএকটি শূন্য স্ট্রিংয়ের সাথে মানটির কোনও অঙ্ক প্রতিস্থাপন করে দেখুন man -P 'less +/parameter\/' bash-zফলাফলের স্ট্রিংয়ের শূন্য দৈর্ঘ্য রয়েছে কিনা তা পরীক্ষা করে।

আপনি যদি $iখালি থাকায় মামলাটি বাদ দিতে চান তবে আপনি এই নির্মাণগুলির একটি ব্যবহার করতে পারেন:

test -n "$i" && test -z "${i//[0-9]}" && echo digits || echo not a number
[[ -n "$i" && -z "${i//[0-9]}" ]] && echo digits || echo not a number

থাম্বস আপ বিশেষত man -P 'less +/parameter\/' bashঅংশ জন্য। প্রতিদিন নতুন কিছু শিখতে। :)
ডেভিড

@ এসজাস আপনি সহজেই \-সমস্যাটি সমাধান করার জন্য নিয়মিত অভিব্যক্তি যোগ করতে পারেন । [0-9\-\.\+]ফ্লোট এবং স্বাক্ষরিত সংখ্যার জন্য অ্যাকাউন্টে ব্যবহার করুন ।
ব্যবহারকারী2683246

@ জাজস ঠিক আছে, আমার দোষ
user2683246

@ sjasecho $i | python -c $'import sys\ntry:\n float(sys.stdin.read().rstrip())\nexcept:\n sys.exit(1)' && echo yes || echo no
user2683246

9

আমার সমস্যার জন্য, আমাকে কেবল এটি নিশ্চিত করা দরকার যে কোনও ব্যবহারকারী দুর্ঘটনাক্রমে কিছু পাঠ্য প্রবেশ না করে আমি এটিকে সহজ এবং পঠনযোগ্য রাখার চেষ্টা করেছি

isNumber() {
    (( $1 )) 2>/dev/null
}

ম্যান পেজ অনুসারে এটি আমার যা করতে চায় তা অনেক বেশি করে

যদি অভিব্যক্তির মান শূন্য-না হয়, ফেরতের স্থিতি 0 হয়

স্ট্রিংগুলির জন্য দুষ্টু ত্রুটি বার্তাগুলি প্রতিরোধ করতে যে "সম্ভবত সংখ্যা হতে পারে" আমি ত্রুটি আউটপুটটিকে উপেক্ষা করি

$ (( 2s ))
bash: ((: 2s: value too great for base (error token is "2s")

এটি আরও পছন্দ আইটেমিটারের মতো। তবে দুর্দান্ত ধন্যবাদ!
নাহিল

8

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

if [ -n "$(printf '%s\n' "$var" | sed 's/[0-9]//g')" ]; then
    echo 'is not numeric'
else
    echo 'is numeric'
fi

মূলত এটি কেবল ইনপুট থেকে সমস্ত অঙ্ক সরিয়ে দেয় এবং যদি আপনি একটি শূন্য-দৈর্ঘ্যের স্ট্রিংটি রেখে থাকেন তবে এটি কোনও সংখ্যা নয়।


এটি একটি খালি জন্য ব্যর্থ var
gniourf_gniourf

অথবা চলন্ত নিউলাইন বা এর মতো কিছু সহ ভেরিয়েবলগুলির জন্য $'0\n\n\n1\n\n\n2\n\n\n3\n'
gniourf_gniourf

7

এখনও মন্তব্য করতে পারছি না তাই আমি আমার নিজের উত্তর যুক্ত করব, যা বাশ প্যাটার্ন ম্যাচটি ব্যবহার করে গ্লেন জ্যাকম্যানের উত্তরের একটি এক্সটেনশন।

আমার আসল প্রয়োজনটি সংখ্যাগুলি সনাক্ত করা এবং পূর্ণসংখ্যা এবং ভাসমানগুলির মধ্যে পার্থক্য করা। ফাংশন সংজ্ঞাগুলি কেটে নেওয়া:

function isInteger() {
    [[ ${1} == ?(-)+([0-9]) ]]
}

function isFloat() {
    [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}

আমি ইউনিট টেস্টিং ব্যবহার করেছি (shUnit2 সহ) আমার নিদর্শনগুলি যেমনটি কাজ করেছে তা যাচাই করতে:

oneTimeSetUp() {
    int_values="0 123 -0 -123"
    float_values="0.0 0. .0 -0.0 -0. -.0 \
        123.456 123. .456 -123.456 -123. -.456
        123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
        123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
        123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
}

testIsIntegerIsFloat() {
    local value
    for value in ${int_values}
    do
        assertTrue "${value} should be tested as integer" "isInteger ${value}"
        assertFalse "${value} should not be tested as float" "isFloat ${value}"
    done

    for value in ${float_values}
    do
        assertTrue "${value} should be tested as float" "isFloat ${value}"
        assertFalse "${value} should not be tested as integer" "isInteger ${value}"
    done

}

নোটস: ইশফ্লোট প্যাটার্নটি দশমিক বিন্দু ( @(.,)) এবং ই প্রতীক ( @(Ee)) সম্পর্কে আরও সহনশীল হতে সংশোধন করা যেতে পারে । আমার ইউনিট পরীক্ষা করে কেবলমাত্র মানগুলি যা হয় পূর্ণসংখ্যা বা ভাসমান, তবে কোনও অবৈধ ইনপুট নয়।


আমি দুঃখিত, কীভাবে সম্পাদনা ফাংশনটি ব্যবহারের উদ্দেশ্যে তা বোঝেনি।
3ronco

6

আমি এটি চেষ্টা করবে:

printf "%g" "$var" &> /dev/null
if [[ $? == 0 ]] ; then
    echo "$var is a number."
else
    echo "$var is not a number."
fi

দ্রষ্টব্য: এটি ন্যান এবং ইনফটিকে সংখ্যা হিসাবে স্বীকৃতি দেয়।


2
হয় পিক্সেলবিটের উত্তরটির ডুপ্লিকেট, বা সম্ভবত আরও ভাল মতামতের জন্য উপযুক্ত ( %fসম্ভবত সম্ভবত যাইহোক ভাল)
মাইকেল

3
আগের স্থিতি কোডটি পরীক্ষা করার পরিবর্তে, কেন এটি কেবল ifনিজের মধ্যে রাখা হয়নি ? এটাই কি if...if printf "%g" "$var" &> /dev/null; then ...
ক্যামিলো মার্টিন

3
এটিতে অন্যান্য সাবধানতা রয়েছে। এটি খালি স্ট্রিং এবং তারের মতো স্ট্রিংকে বৈধতা দেবে 'a
gniourf_gniourf

6

একটি পরিষ্কার উত্তর ইতিমধ্যে @ চারলেস ডুফি এবং অন্যরা দিয়েছেন। একটি খাঁটি বাশ সমাধান নিম্নলিখিত ব্যবহার করা হবে:

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

যদিও আসল সংখ্যার জন্য মূল সংখ্যাটির আগে একটি সংখ্যা থাকা বাধ্যতামূলক নয়

ভাসমান সংখ্যা এবং বৈজ্ঞানিক স্বরলিপি (সি / ফোর্টরানের অনেক প্রোগ্রাম বা অন্যভাবে এভাবে ভাসমানটি রফতানি করবে) এর আরও পুঙ্খানুপুঙ্খ সমর্থন সরবরাহ করতে, এই লাইনের একটি দরকারী সংযোজন নিম্নলিখিত হবে:

string="1.2345E-67"
if [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]?-?[0-9]+$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

সুতরাং আপনি যদি কোনও নির্দিষ্ট প্রকারের সন্ধান করে থাকেন তবে বিভিন্ন ধরণের সংখ্যার পার্থক্য দেখানোর উপায় নিয়ে আসে:

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+$ ]]
then
    echo $string is an integer
elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*$ ]]
then
    echo $string is a float
elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]-?[0-9]+$ ]]
then
    echo $string is a scientific number
else
    echo $string is not a number
fi

দ্রষ্টব্য: আমরা দশমিক এবং বৈজ্ঞানিক স্বরলিপি জন্য সিনট্যাকটিকাল প্রয়োজনীয়তা তালিকাভুক্ত করতে পারি, একটি হ'ল কমেটাকে রেডিক্স পয়েন্ট হিসাবে অনুমোদিত করার পাশাপাশি ""। তারপরে আমরা দৃ as়ভাবে বলব যে এখানে কেবলমাত্র একটিরকম রেডিক্স পয়েন্ট থাকতে হবে। [Ee] ভাসায় দুটি +/- চিহ্ন থাকতে পারে। আমি আউলের কাজ থেকে আরও কিছু নিয়ম শিখেছি এবং '' '' - '' -E-1 '' 0-0 'এর মতো খারাপ স্ট্রিংয়ের বিরুদ্ধে পরীক্ষা করেছি। এখানে আমার রেজেক্স / সাবস্ট্রিং / এক্সপ্রেস সরঞ্জামগুলি মনে হচ্ছে যা ধরে রাখা হয়েছে:

parse_num() {
 local r=`expr "$1" : '.*\([.,]\)' 2>/dev/null | tr -d '\n'` 
 nat='^[+-]?[0-9]+[.,]?$' \
 dot="${1%[.,]*}${r}${1##*[.,]}" \
 float='^[\+\-]?([.,0-9]+[Ee]?[-+]?|)[0-9]+$'
 [[ "$1" == $dot ]] && [[ "$1" =~ $float ]] || [[ "$1" =~ $nat ]]
} # usage: parse_num -123.456

6
[[ $1 =~ ^-?[0-9]+$ ]] && echo "number"

-নেতিবাচক সংখ্যা অন্তর্ভুক্ত করতে ভুলবেন না !


বাশের সর্বনিম্ন সংস্করণটি কী? আমি কেবল বাশ পেয়েছি: শর্তসাপেক্ষ বাইনারি অপারেটর প্রত্যাশিত ব্যাশ: অপ্রত্যাশিত টোকেনের নিকটে সিনট্যাক্স ত্রুটি `= ~ '
পল হারগ্রিভস

1
@ পলহর্গগ্রাভগুলি =~কমপক্ষে ব্যাস 3.0.০ হিসাবে উপস্থিত ছিল।
গিলস 'অশুভ হওয়া বন্ধ করুন'

@ পলহর্গিগ্রেভস সম্ভবত আপনার প্রথম অপারেন্ডে সমস্যা ছিল, যেমন অনেকগুলি উদ্ধৃতি চিহ্ন বা অনুরূপ
জোশুয়া ক্লেটন

@ জোশুয়া ক্লেটন আমি সংস্করণটি সম্পর্কে জিজ্ঞাসা করেছি কারণ এটি একটি সোলারিস 7 বাক্সে খুব পুরানো বাশ, যা আমাদের এখনও রয়েছে এবং এটি সমর্থন করে না = ~
পল হারগ্রাভেস

6

এটি ব্যবহার করে অর্জন করা যেতে পারে grepপ্রশ্নের মধ্যে পরিবর্তনশীল একটি বর্ধিত নিয়মিত প্রকাশের সাথে মেলে কিনা তা ।

পরীক্ষার পূর্ণসংখ্যা 1120:

yournumber=1120
if echo "$yournumber" | grep -qE '^[0-9]+$'; then
    echo "Valid number."
else
    echo "Error: not a number."
fi

আউটপুট: Valid number.

অ-পূর্ণসংখ্যা পরীক্ষা করুন 1120a:

yournumber=1120a
if echo "$yournumber" | grep -qE '^[0-9]+$'; then
    echo "Valid number."
else
    echo "Error: not a number."
fi

আউটপুট: Error: not a number.


ব্যাখ্যা

  • দ্য grep, -Eসুইচ আমাদের বর্ধিত নিয়মিত এক্সপ্রেশন ব্যবহার করতে দেয় '^[0-9]+$'। এই নিয়মিত অভিব্যক্তিটির অর্থ হল চলকটির শুরুতে শুরু থেকে শেষ পর্যন্ত 9 টির []মধ্যে কেবল 0-9শূন্যের সংখ্যা থাকা উচিত এবং কমপক্ষে কমপক্ষে থাকতে হবে^$+ একটি অক্ষর।
  • দ্য grep, দ্য-q শান্ত সুইচ হোক বা না হোক কিছু খুঁজে বের করে কোন আউটপুট বন্ধ হয়ে যাবে।
  • ifএর প্রস্থান স্থিতি পরীক্ষা করে grep। প্রস্থান স্থিতি 0মানে সাফল্য এবং এর চেয়ে বড় কিছু মানে একটি ত্রুটি। grepকমান্ডের একটি প্রস্থান অবস্থা হয়েছে 0যদি এটি একটি ম্যাচ খুঁজে পায় এবং 1যখন এটা করে না;

সুতরাং ifপরীক্ষায় এটি সমস্ত একসাথে রাখা , আমরা echoপরিবর্তনশীল $yournumberএবং |পাইপ grepযা -qসুইচ সঙ্গে নীরবে -Eবর্ধিত নিয়মিত অভিব্যক্তি '^[0-9]+$'অভিব্যক্তি মেলে । সফলতার সাথে কোনও মিল খুঁজে পাওয়া গেলে এবং যদি এটি না পাওয়া যায় তবে এর প্রস্থান স্থিতি grepহবে । মেলতে সফল হলে, আমরা । যদি এটি মেলে ব্যর্থ হয়, আমরা ।0grep1echo "Valid number."echo "Error: not a number."


ফ্লোটস বা ডাবলসের জন্য

আমরা কেবল নিয়মিত ভাবটি থেকে পরিবর্তন '^[0-9]+$'করতে পারি'^[0-9]*\.?[0-9]+$' ভাসে বা ডাবলস জন্য।

পরীক্ষা ভাসা 1120.01:

yournumber=1120.01
if echo "$yournumber" | grep -qE '^[0-9]*\.?[0-9]+$'; then
    echo "Valid number."
else
    echo "Error: not a number."
fi

আউটপুট: Valid number.

পরীক্ষা ভাসা 11.20.01:

yournumber=11.20.01
if echo "$yournumber" | grep -qE '^[0-9]*\.?[0-9]+$'; then
    echo "Valid number."
else
    echo "Error: not a number."
fi

আউটপুট: Error: not a number.


নেতিবাচকদের জন্য

নেতিবাচক পূর্ণসংখ্যার শুধু থেকে রেগুলার এক্সপ্রেশন পরিবর্তন অনুমতি দিতে '^[0-9]+$'করার '^\-?[0-9]+$'

নেতিবাচক ভাসে বা দ্বিগুণ শুধু থেকে রেগুলার এক্সপ্রেশন পরিবর্তন অনুমতি দিতে '^[0-9]*\.?[0-9]+$'করার '^\-?[0-9]*\.?[0-9]+$'


আপনি ঠিক বলেছেন, @ চার্লস ডফি। ধন্যবাদ। আমি উত্তর পরিষ্কার।
জোসেফ শিহ

ঠিক আবার আপনি, চার্লস ডাফি সংশোধন করা হয়েছে!
জোসেফ শিহ

1
LGTM; সম্পাদিত উত্তরটির আমার +1 রয়েছে। এই মুহুর্তে আমি কেবল ভিন্ন ভিন্ন জিনিসগুলি হ'ল নির্ভুলতার চেয়ে মতামতের বিষয়গুলি (f / e, এর [-]পরিবর্তে \-এবং [.]পরিবর্তে ব্যবহার করা \.কিছুটা ভার্জোজ), তবে এর অর্থ আপনার স্ট্রিংগুলি পরিবর্তন করতে হবে না যদি তারা ' এমন পরিস্থিতিতে ব্যবহৃত হয় যেখানে ব্যাকস্ল্যাশগুলি গ্রাস হয়)।
চার্লস ডাফি

4

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_03.html

আপনি বাশের চরিত্রের ক্লাসগুলিও ব্যবহার করতে পারেন।

if [[ $VAR = *[[:digit:]]* ]]; then
 echo "$VAR is numeric"
else
 echo "$VAR is not numeric"
fi

সংখ্যাগুলিতে স্থান, দশমিক বিন্দু এবং ভাসমান পয়েন্টের জন্য "ই" বা "ই" অন্তর্ভুক্ত থাকবে।

তবে, আপনি যদি কোনও সি-স্টাইলের হেক্স নম্বর উল্লেখ করেন, যেমন "0xffff" বা "0XFFFF", [[: ডিজিট:]] সত্য হয়। এখানে কিছুটা ফাঁদ, বাশ আপনাকে "0xAZ00" এর মতো কিছু করতে দেয় এবং এখনও এটি একটি অঙ্ক হিসাবে গণনা করে (এটি জিসিসি সংকলকগুলির কিছু বিস্ময়কর গন্ধ থেকে নয় যা আপনাকে 16 এর বাইরে অন্য ঘাঁটির জন্য 0x স্বরলিপি ব্যবহার করতে পারে ??? )

আপনি যদি হেক্স নম্বরগুলি গ্রহণ করতে না চান তবে আপনার ইনপুট পুরোপুরি অবিশ্বস্ত থাকলে পরীক্ষার আগে আপনি "0x" বা "0 এক্স" এর পরীক্ষা করতে চাইতে পারেন। এটি দ্বারা সম্পাদিত হবে:

if [[ ${VARIABLE:1:2} = "0x" ]] || [[ ${VARIABLE:1:2} = "0X" ]]; then echo "$VAR is not numeric"; fi

17
[[ $VAR = *[[:digit:]]* ]]সত্য ফিরে আসবে যদি পরিবর্তনশীল রয়েছে একটি সংখ্যা, যদি না হয় একটি পূর্ণসংখ্যা।
গ্লেন জ্যাকম্যান

[[ "z3*&" = *[[:digit:]]* ]] && echo "numeric"কপি করে প্রিন্ট numeric। বাশ সংস্করণে পরীক্ষিত 3.2.25(1)-release
জামাদিয়ান

1
@ সমালোচনাযোগ্য, আপনার সমাধানটি কমপক্ষে, অন্য কোনও অক্ষর দ্বারা ঘেরাও (বা না) একটি স্ট্রিংযুক্ত সেই স্ট্রিংগুলি সনাক্ত করে। আমি হ্রাস পেয়েছি।
জ্যামডিয়ান

স্পষ্টতই সঠিক পন্থা হ'ল এটিকে বিপরীত করা এবং ব্যবহার করা[[ -n $VAR && $VAR != *[^[:digit:]]* ]]
eschwartz

@ ইশওয়ার্টজ, আপনার সমাধানটি নেতিবাচক সংখ্যার সাথে কাজ করে না
অ্যাঞ্জেল

4

সবচেয়ে সহজ উপায় এটিতে অ-অঙ্কিত অক্ষর রয়েছে কিনা তা পরীক্ষা করা। আপনি সমস্ত অঙ্কের অক্ষরকে কিছুই সহ প্রতিস্থাপন করুন এবং দৈর্ঘ্যের জন্য পরীক্ষা করুন। দৈর্ঘ্য থাকলে এটি কোনও সংখ্যা নয়।

if [[ ! -n ${input//[0-9]/} ]]; then
    echo "Input Is A Number"
fi

2
নেতিবাচক সংখ্যাগুলি পরিচালনা করতে আরও জটিল পদ্ধতির প্রয়োজন হবে।
অ্যান্ডি

... বা একটি alচ্ছিক ইতিবাচক চিহ্ন।
ট্রিপলি

আপনি কীভাবে এটি করতে জানেন যদি @ ট্রিপলি আপনার পদ্ধতির সাথে দেখতে চাই।
অ্যান্ডি 15

4

যেহেতু আমি ইদানীং এর সাথে এই ইউনিট পরীক্ষার সাথে কার্ট্টুর অ্যাপোচকে সবচেয়ে বেশি ছটফট করতে হয়েছিল। আমি কোডটি সংশোধন করেছি এবং আরও কিছু সমাধানও যুক্ত করেছি, ফলাফলগুলি দেখার জন্য নিজে চেষ্টা করে দেখুন:

#!/bin/bash

    # N={0,1,2,3,...} by syntaxerror
function isNaturalNumber()
{
 [[ ${1} =~ ^[0-9]+$ ]]
}
    # Z={...,-2,-1,0,1,2,...} by karttu
function isInteger() 
{
 [[ ${1} == ?(-)+([0-9]) ]]
}
    # Q={...,-½,-¼,0.0,¼,½,...} by karttu
function isFloat() 
{
 [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}
    # R={...,-1,-½,-¼,0.E+n,¼,½,1,...}
function isNumber()
{
 isNaturalNumber $1 || isInteger $1 || isFloat $1
}

bools=("TRUE" "FALSE")
int_values="0 123 -0 -123"
float_values="0.0 0. .0 -0.0 -0. -.0 \
    123.456 123. .456 -123.456 -123. -.456 \
    123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
    123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
    123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
false_values="blah meh mooh blah5 67mooh a123bc"

for value in ${int_values} ${float_values} ${false_values}
do
    printf "  %5s=%-30s" $(isNaturalNumber $value) ${bools[$?]} $(printf "isNaturalNumber(%s)" $value)
    printf "%5s=%-24s" $(isInteger $value) ${bools[$?]} $(printf "isInteger(%s)" $value)
    printf "%5s=%-24s" $(isFloat $value) ${bools[$?]} $(printf "isFloat(%s)" $value)
    printf "%5s=%-24s\n" $(isNumber $value) ${bools[$?]} $(printf "isNumber(%s)" $value)
done

সুতরাং isNumber ()ড্যাশস , কমা এবং তাত্পর্যপূর্ণ স্বরলিপি অন্তর্ভুক্ত করে এবং তাই পূর্ণসংখ্যার ও ভাসমান স্থানে সত্য ফিরিয়ে দেয় যেখানে অন্যদিকে ফ্লাট () পূর্ণসংখ্যার মানগুলিতে FALSE প্রদান করে এবং ইঞ্জিওয়েজার () তেমনিভাবে ফ্লোটে মিথ্যা প্রদান করে। আপনার সুবিধার্থে এক লাইনার হিসাবে সমস্ত:

isNaturalNumber() { [[ ${1} =~ ^[0-9]+$ ]]; }
isInteger() { [[ ${1} == ?(-)+([0-9]) ]]; }
isFloat() { [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]; }
isNumber() { isNaturalNumber $1 || isInteger $1 || isFloat $1; }

ব্যক্তিগতভাবে আমি functionকীওয়ার্ডটি সরিয়ে ফেলব কারণ এটি কোনও কার্যকর কাজ করে না। এছাড়াও, আমি ফিরে আসার মানগুলির কার্যকারিতা সম্পর্কে নিশ্চিত নই। অন্যথায় নির্দিষ্ট না করা পর্যন্ত, ফাংশনগুলি শেষ কমান্ডের প্রস্থান স্থিতি ফিরিয়ে দেবে, সুতরাং আপনার returnনিজের কিছু করার প্রয়োজন নেই।
টম ফেনেক

চমৎকার, সত্যই returnগুলি বিভ্রান্ত করছে এবং এটিকে কম পাঠযোগ্য করে তোলে। functionকীওয়ার্ড ব্যবহার করা বা না করা ব্যক্তিগত স্বাদের প্রশ্ন হ'ল কমপক্ষে আমি কিছু স্থান বাঁচাতে এক লাইনার থেকে সেগুলি সরিয়েছি। ধন্যবাদ.
3ronco

ভুলে যাবেন না যে এক-লাইন সংস্করণগুলির জন্য পরীক্ষার পরে সেমিকোলনগুলির প্রয়োজন।
টম ফেনেক

2
isNumber এর কোনও সংখ্যা রয়েছে এমন কোনও স্ট্রিংয়ে 'সত্য' ফেরত দেবে।
DrStrangepork

@ ডিস্ট্রঞ্জরপর্ক অবশ্যই, আমার ভুয়া_মূল্যের অ্যারেটি সে ক্ষেত্রে অনুপস্থিত। আমি এটি দেখতে হবে। ইঙ্গিতটির জন্য ধন্যবাদ।
3ronco

4

আমি এক্সপ্রেস ব্যবহার করি । যদি আপনি একটি অ-সংখ্যাগত মানতে একটি শূন্য যোগ করার চেষ্টা করেন তবে এটি একটি শূন্যকে ফিরে দেয়:

if expr -- "$number" + 0 > /dev/null 2>&1
then
    echo "$number is a number"
else
    echo "$number isn't a number"
fi

আপনার অ-পূর্ণসংখ্যার প্রয়োজন হলে বিসি ব্যবহার করা সম্ভব হতে পারে , তবে আমি বিশ্বাস করি না যে bcবেশিরভাগ একই আচরণ রয়েছে। অ-সংখ্যাতে শূন্য যুক্ত করা আপনাকে শূন্য করে এবং এটিও শূন্যের মান দেয়। হতে পারে আপনি একত্রিত করতে পারেন bcএবং exprbcশূন্য যোগ করতে ব্যবহার করুন $number। উত্তরটি যদি হয় 0তবে তা শূন্য নয় exprযাচাই করার চেষ্টা করুন $number


1
এটা বরং খারাপ। এটিকে কিছুটা উন্নত করতে আপনার ব্যবহার করা উচিত expr -- "$number" + 0; তবু এটি এখনও যে ভান করবে 0 isn't a number। থেকে man expr:Exit status is 0 if EXPRESSION is neither null nor 0, 1 if EXPRESSION is null or 0,
gniourf_gniourf

3

আমি আলবার্তো জ্যাকাকনির উত্তরটি পছন্দ করি।

if [ "$var" -eq "$var" ] 2>/dev/null; then

গুরুত্বপূর্ণ পূর্বশর্ত: - কোনও সাবশেল তৈরি হয়নি - কোন পার্সার আহবান করা হয়নি - বেশিরভাগ শেল অ্যাপ্লিকেশনগুলি আসল সংখ্যা ব্যবহার করে না

তবে যদি $varজটিল হয় (উদাহরণস্বরূপ কোনও সহযোগী অ্যারে অ্যাক্সেস), এবং যদি সংখ্যাটি একটি অ-নেতিবাচক পূর্ণসংখ্যার (সর্বাধিক ব্যবহারের ক্ষেত্রে) হয়ে থাকে, তবে সম্ভবত এটি আরও কার্যকর?

if [ "$var" -ge 0 ] 2> /dev/null; then ..

2

আমি উল্লিখিত অন্যান্য উত্তর হিসাবে প্রিন্টফ ব্যবহার করি, যদি আপনি "% f" বা "% i" ফর্ম্যাট স্ট্রিং সরবরাহ করেন তবে তা আপনার জন্য যাচাই করবে। চেকগুলি পুনরায় উদ্ভাবনের চেয়ে সহজ, সিনট্যাক্সটি সহজ এবং সংক্ষিপ্ত এবং প্রিন্টফ সর্বব্যাপী। সুতরাং এটি আমার মতে এটি একটি শালীন পছন্দ - আপনি নীচের ধারণাটি বিভিন্ন বিষয় যাচাই করতে ব্যবহার করতে পারেন, এটি কেবল সংখ্যা যাচাইয়ের জন্য দরকারী নয়।

declare  -r CHECK_FLOAT="%f"  
declare  -r CHECK_INTEGER="%i"  

 ## <arg 1> Number - Number to check  
 ## <arg 2> String - Number type to check  
 ## <arg 3> String - Error message  
function check_number() { 
  local NUMBER="${1}" 
  local NUMBER_TYPE="${2}" 
  local ERROR_MESG="${3}"
  local -i PASS=1 
  local -i FAIL=0   
  case "${NUMBER_TYPE}" in 
    "${CHECK_FLOAT}") 
        if ((! $(printf "${CHECK_FLOAT}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
    "${CHECK_INTEGER}") 
        if ((! $(printf "${CHECK_INTEGER}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
                     *) 
        echo "Invalid number type format: ${NUMBER_TYPE} to check_number()." 1>&2
        echo "${FAIL}"
        ;;                 
   esac
} 

>$ var=45

>$ (($(check_number $var "${CHECK_INTEGER}" "Error: Found $var - An integer is required."))) && { echo "$var+5" | bc; }


2

নিয়মিত অভিব্যক্তি বনাম প্যারামিটার সম্প্রসারণ

চার্লস ডফির উত্তর হিসাবে কাজ, তবে কেবল ব্যবহারনিয়মিত অভিব্যক্তি , এবং আমি এটি ধীর হতে জানি, আমি কেবল অন্যটি ব্যবহার করে অন্য উপায় দেখাতে চাইপ্যারামিটার সম্প্রসারণ :

ইতিবাচক পূর্ণসংখ্যার জন্য:

is_num() { [ "$1" ] && [ -z "${1//[0-9]}" ] ;}

পূর্ণসংখ্যার জন্য:

is_num() { 
    local chk=${1#[+-]};
    [ "$chk" ] && [ -z "${chk//[0-9]}" ]
}

তারপরে ভাসার জন্য:

is_num() { 
    local chk=${1#[+-]};
    chk=${chk/.}
    [ "$chk" ] && [ -z "${chk//[0-9]}" ]
}

প্রাথমিক অনুরোধের সাথে মেলে:

set -- "foo bar"
is_num "$1" && VAR=$1 || echo "need a number"
need a number

set -- "+3.141592"
is_num "$1" && VAR=$1 || echo "need a number"

echo $VAR
+3.141592

এখন একটু তুলনা:

চার্লস ডাফির উত্তরের উপর ভিত্তি করে একই চেক রয়েছে :

cdIs_num() { 
    local re='^[+-]?[0-9]+([.][0-9]+)?$';
    [[ $1 =~ $re ]]
}

কিছু পরীক্ষা:

if is_num foo;then echo It\'s a number ;else echo Not a number;fi
Not a number
if cdIs_num foo;then echo It\'s a number ;else echo Not a number;fi
Not a number
if is_num 25;then echo It\'s a number ;else echo Not a number;fi
It's a number
if cdIs_num 25;then echo It\'s a number ;else echo Not a number;fi
It's a number
if is_num 3+4;then echo It\'s a number ;else echo Not a number;fi
Not a number
if cdIs_num 3+4;then echo It\'s a number ;else echo Not a number;fi
Not a number
if is_num 3.1415;then echo It\'s a number ;else echo Not a number;fi
It's a number
if cdIs_num 3.1415;then echo It\'s a number ;else echo Not a number;fi
It's a number

আচ্ছা, ঠিক আছে. এখন কত সময় লাগবে এই সমস্ত (আমার রাস্পবেরি পাইতে):

time for i in {1..1000};do is_num +3.14159265;done
real    0m2.476s
user    0m1.235s
sys     0m0.000s

তারপরে নিয়মিত প্রকাশের সাথে:

time for i in {1..1000};do cdIs_num +3.14159265;done
real    0m4.363s
user    0m2.168s
sys     0m0.000s

আমি সম্মত হই, যাইহোক, আমি রেজিেক্স ব্যবহার না করা পছন্দ করি, যখন আমি প্যারামিটার সম্প্রসারণ ব্যবহার করতে পারি ... আর আর অপব্যবহার করা বাশ স্ক্রিপ্টকে ধীরে ধীরে করে দেবে
এফ হাউরি

উত্তর সম্পাদিত: দরকার নেই extglob(এবং আরও দ্রুত)!
এফ। হাউরি

@ চার্লসডুফি, আমার রাস্পবেরি পাইতে, 1000 পুনরাবৃত্তিটি আমার সংস্করণ সহ 2,5 সেকেন্ড এবং আপনার সংস্করণ সহ 4,4 সেকেন্ড লাগবে!
এফ। হাউরি

এ নিয়ে তর্ক করতে পারি না। 👍
চার্লস ডাফি

1

নেতিবাচক সংখ্যাগুলি ধরতে:

if [[ $1 == ?(-)+([0-9.]) ]]
    then
    echo number
else
    echo not a number
fi

এছাড়াও, এর জন্য প্রথমে সক্ষম করার জন্য বর্ধিত গ্লোববিং প্রয়োজন। এটি বাশ-কেবল বৈশিষ্ট্য যা ডিফল্টরূপে অক্ষম।
ট্রিপলি

@ ট্রিপলির বর্ধিত গ্লোববিং == বা! When the ‘==’ and ‘!=’ operators are used, the string to the right of the operator is considered a pattern and matched according to the rules described below in Pattern Matching, as if the extglob shell option were enabled. gnu.org/software/bash/manual/bashref.html#index-_005b_005b
বদর এলমার্স

@ ব্যাডারএলমার্স আপডেটের জন্য ধন্যবাদ। এটি একটি নতুন আচরণ বলে মনে হচ্ছে যা আমার বাশ 3.2.57 (ম্যাকোস মোজাভে) -তে সত্য নয়। আমি দেখতে পাচ্ছি যে আপনি এটি ৪.৪-এ বর্ণনা করেছেন।
ট্রিপলি

1

আপনি এইভাবে "লেট" ব্যবহার করতে পারেন:

[ ~]$ var=1
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=01
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=toto
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s not a number
[ ~]$ 

তবে আমি এই থ্রেডের কয়েকটি উত্তরের মতো "= ~" ব্যাশ 3+ অপারেটরটি ব্যবহার করতে পছন্দ করি।


5
এটি অত্যন্ত বিপজ্জনক। শেলের মধ্যে অবৈধ গণিত মূল্যায়ন করবেন না। এটি প্রথমে অন্য কোনওভাবে যাচাই করতে হবে।
ormaaj

1
printf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."

-\?আপনি যদি নেতিবাচক পূর্ণসংখ্যাকে গ্রহণ না করেন তবে গ্রাঙ্কের সাথে মিলে যাওয়া প্যাটার্নটি সরিয়ে ফেলুন ।


2
ব্যাখ্যাের অভাবে ডাউনভোট করুন। কিভাবে কাজ করে? এটি জটিল এবং ভঙ্গুর দেখাচ্ছে এবং এটি কী গ্রহণ করবে তা স্পষ্ট নয় exactly (উদাহরণস্বরূপ, প্রয়োজনীয় স্থানগুলি অপসারণ করা কি গুরুত্বপূর্ণ? কেন? এটি এমবেডেড স্পেস সহ একটি সংখ্যা একটি বৈধ সংখ্যা, যা পছন্দসই হতে পারে না
বলবে

1

এখানে নিয়মিত প্রকাশের সাথে একই জিনিসটি ঘটেছে যা পুরো অংশ এবং দশমিক অংশগুলি বিন্দুর সাহায্যে পৃথক করে test

re="^[0-9]*[.]{0,1}[0-9]*$"

if [[ $1 =~ $re ]] 
then
   echo "is numeric"
else
  echo "Naahh, not numeric"
fi

আপনার উত্তর কেন অন্যান্য পুরানো উত্তরগুলির তুলনায় মৌলিকভাবে পৃথক, উদাহরণস্বরূপ, চার্লস ডাফির উত্তরটি ব্যাখ্যা করতে পারেন? ঠিক আছে, আপনার উত্তরটি আসলে ভেঙে গেছে কারণ এটি একটি একক সময়কে বৈধতা দেয়.
gniourf_gniourf

এখানে একক পিরিয়ড বোঝার জন্য নিশ্চিত নন ... এটি এক বা শূন্য সময়কাল প্রত্যাশিত .... তবে সঠিক কিছুই মৌলিকভাবে আলাদা নয়, সবেমাত্র রেজেক্সকে সহজভাবে পড়তে পেলাম।
জেরোম

এছাড়াও * ব্যবহার করে আরও বাস্তব বিশ্বের
জেরোম

জিনিসটি হ'ল আপনি খালি স্ট্রিং a=''এবং স্ট্রিংয়ের সাথে মিলে যাচ্ছেন কেবলমাত্র a='.'আপনার কোডটি কিছুটা ভাঙার ফলে একটি সময়কাল থাকে ...
gniourf_gniourf

0

আমি নিম্নলিখিতটি ব্যবহার করি (পূর্ণসংখ্যার জন্য):

## ##### constants
##
## __TRUE - true (0)
## __FALSE - false (1)
##
typeset -r __TRUE=0
typeset -r __FALSE=1

## --------------------------------------
## isNumber
## check if a value is an integer 
## usage: isNumber testValue 
## returns: ${__TRUE} - testValue is a number else not
##
function isNumber {
  typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
  [ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
}

isNumber $1 
if [ $? -eq ${__TRUE} ] ; then
  print "is a number"
fi

প্রায় সঠিক (আপনি খালি স্ট্রিং গ্রহণ করছেন) তবে কৃতজ্ঞতাবশত অবক্ষয়ের দিক থেকে জটিল।
গিলস 'তাই খারাপ হওয়া বন্ধ করুন'

2
ভুল: আপনি গ্রহণ করছেন -n, ইত্যাদি (কারণ echo), এবং আপনি চলন্ত নিউলাইনগুলি (কারণ কারণে $(...)) সহ ভেরিয়েবল গ্রহণ করছেন । এবং printযাইহোক, একটি বৈধ শেল কমান্ড নয়।
gniourf_gniourf

0

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

[[ "${var//*([[:digit:]])}" ]]; && echo "$var is not numeric" || echo "$var is numeric"

এটি প্রতি: ডিজিট: শ্রেণি অক্ষরকে $ var এ সরিয়ে দেয় এবং খালি স্ট্রিংয়ের সাথে রেখে দেওয়া হয় কিনা তা পরীক্ষা করে, যার অর্থ আসলটি কেবল সংখ্যা ছিল।

আমি এটি সম্পর্কে যা পছন্দ করি তা হ'ল এর ছোট পদচিহ্ন এবং নমনীয়তা। এই ফর্মটিতে এটি কেবলমাত্র সীমানাবিহীন, বেস 10 পূর্ণসংখ্যার জন্য কাজ করে, যদিও আপনি এটি অন্যান্য প্রয়োজন অনুসারে প্যাটার্ন ম্যাচিং ব্যবহার করতে পারেন।


মুর্চির সমাধানটি পড়াতে, এটি প্রায় আমার মতো দেখতে লাগে তবে "সেড স্টাইল" এর পরিবর্তে নিয়মিত স্ট্রিং প্রতিস্থাপন ব্যবহার করা হয়। উভয়ই প্যাটার্ন মিলের জন্য একই নিয়ম ব্যবহার করে এবং হ'ল, আফাইক, বিনিময়যোগ্য সমাধান।
আতা

sedআপনার পলিটিকেশনটি হ'ল পসিক্স bash। উভয়ের ব্যবহার রয়েছে
v010dya

0

কুইক অ্যান্ড ডার্টি: আমি জানি এটি সবচেয়ে মার্জিত উপায় নয়, তবে আমি সাধারণত এটিতে একটি শূন্য যুক্ত করে ফলাফলটি পরীক্ষা করি test তাই ভালো:

function isInteger {
  [ $(($1+0)) != 0 ] && echo "$1 is a number" || echo "$1 is not a number"
 }

x=1;      isInteger $x
x="1";    isInteger $x
x="joe";  isInteger $x
x=0x16 ;  isInteger $x
x=-32674; isInteger $x   

$ (($ 1 + 0)) 0 বা বোমা ফিরবে যদি $ 1 পূর্ণসংখ্যা না হয়। উদাহরণ স্বরূপ:

function zipIt  { # quick zip - unless the 1st parameter is a number
  ERROR="not a valid number. " 
  if [ $(($1+0)) != 0 ] ; then  # isInteger($1) 
      echo " backing up files changed in the last $1 days."
      OUT="zipIt-$1-day.tgz" 
      find . -mtime -$1 -type f -print0 | xargs -0 tar cvzf $OUT 
      return 1
  fi
    showError $ERROR
}

দ্রষ্টব্য: আমি অনুমান করি যে আমি কখনও ভাসা বা মিশ্রিত প্রকারগুলি পরীক্ষা করার চিন্তা করিনি যা পুরো স্ক্রিপ্টকে বোমা বানিয়ে দেবে ... আমার ক্ষেত্রে, আমি এটিকে আরও বেশি কিছু করতে চাইনি। আমি মুর্চির সমাধান এবং ডফির রেজেক্স নিয়ে ঘুরে বেড়াতে যাচ্ছি - তারা ব্যাশ কাঠামোর মধ্যে সবচেয়ে শক্তিশালী বলে মনে হচ্ছে ...


4
এটি পাটিগণিতের মত প্রকাশগুলি যেমন গ্রহণ 1+1করে তবে শীর্ষস্থানীয়গুলির সাথে কিছু ধনাত্মক পূর্ণসংখ্যা প্রত্যাখ্যান করে 0(কারণ 08এটি একটি অবৈধ অক্টাল ধ্রুবক)।
গিলস 'অসন্তুষ্ট হওয়া বন্ধ করুন'

2
এই অন্যান্য বিষয় খুব রয়েছে: 0কোনো সংখ্যা নয়, এবং এটি নির্বিচারে কোড ইনজেকশন সাপেক্ষে, এটা চেষ্টা করুন: isInteger 'a[$(ls)]'। ওহো।
gniourf_gniourf

1
এবং এর প্রসার $((...))অযোগ্য, একটি সংখ্যা IFS=123এটি পরিবর্তন করবে।
ইসহাক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.