BASH- এ তালিকায় কোনও পরিবর্তনশীল উপস্থিত কিনা তা আমি কীভাবে পরীক্ষা করব How


137

আমি ব্যাশে একটি স্ক্রিপ্ট লেখার চেষ্টা করছি যা ব্যবহারকারীর ইনপুটটির বৈধতা পরীক্ষা করে।
আমি xবৈধ মানগুলির তালিকার সাথে ইনপুটটি (পরিবর্তনশীল বলুন ) মেলাতে চাই ।

এই মুহুর্তে আমি যা নিয়ে এসেছি তা হ'ল:

for item in $list
do
    if [ "$x" == "$item" ]; then
        echo "In the list"
        exit
    fi
done

আমার প্রশ্নটি হল যদি এটি করার কোনও সহজ উপায় থাকে তবে বেশিরভাগ প্রোগ্রামিং ভাষার জন্য
এটির মতো কিছু list.contains(x)

সংযোজন:
বলুন তালিকাটি হ'ল:

list="11 22 33"

আমার কোডটি কেবল সেই মানগুলির জন্য বার্তা প্রতিধ্বনিত করবে যেহেতু listএকটি অ্যারে হিসাবে বিবেচিত হবে এবং একটি স্ট্রিং নয়, সমস্ত স্ট্রিং ম্যানিপুলেশনগুলি বৈধ হবে 1যখন আমি চাই এটি ব্যর্থ হোক।

উত্তর:


142
[[ $list =~ (^|[[:space:]])$x($|[[:space:]]) ]] && echo 'yes' || echo 'no'

বা একটি ফাংশন তৈরি করুন:

contains() {
    [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]] && exit(0) || exit(1)
}

এটি ব্যবহার করতে:

contains aList anItem
echo $? # 0: match, 1: failed

37
হওয়া উচিত[[ $list =~ (^| )$x($| ) ]] && echo 'yes' || echo 'no'
মাত্তে আকসেনভ

12
যদি ব্যবহারকারী x=.
ইনপুটটিতে

4
এটি কোন মিথ্যা positives / নেগেটিভ দিতে হবে: contains () { [[ "$1" =~ (^|[[:space:]])"$2"($|[[:space:]]) ]]; }
স্কোজিন

6
আরো একটি সংক্ষিপ্ত সমাধান: [[ " $list " =~ " $x " ]] && echo 'yes' || echo 'no'। এটি সঠিকভাবে ধরে নেওয়া যায় যে স্থানটি বিভাজক এবং $xএতে স্থান নেই
টিয়ানরেন লিউ

2
আমি মনে করি একটি "ইন ইন" ফাংশন ব্যবহার করা ভাল তবে আপনি isIn()আইটেমটি পরামিতিতে লিখতে পারেন। এছাড়াও আপনি echoexit[[ $2 =~ (^|[[:space:]])$1($|[[:space:]]) ]] && echo 1 || echo 0result=$(isIn "-t" "-o -t 45") && echo $result
এটির

34

মাতভে ঠিক বলেছেন, তবে আপনার উচিত $ x উদ্ধৃত করা এবং কোনও ধরণের "স্পেস" (যেমন নতুন লাইন) এর সাথে বিবেচনা করা উচিত

[[ $list =~ (^|[[:space:]])"$x"($|[[:space:]]) ]] && echo 'yes' || echo 'no' 

সুতরাং, যেমন

# list_include_item "10 11 12" "2"
function list_include_item {
  local list="$1"
  local item="$2"
  if [[ $list =~ (^|[[:space:]])"$item"($|[[:space:]]) ]] ; then
    # yes, list include item
    result=0
  else
    result=1
  fi
  return $result
}

তারপর শেষ

`list_include_item "10 11 12" "12"`  && echo "yes" || echo "no"

অথবা

if `list_include_item "10 11 12" "1"` ; then
  echo "yes"
else 
  echo "no"
fi

নোট করুন যে আপনাকে অবশ্যই ""ভেরিয়েবলের ক্ষেত্রে ব্যবহার করতে হবে :

`list_include_item "$my_list" "$my_item"`  && echo "yes" || echo "no"

3
এই সমাধানটি $itemবিশেষ অক্ষরগুলি সমেত এমনকি কার্যকর হয় .( যেমন $listভ্যারিয়েবলটি পরীক্ষার অভ্যন্তরে উদ্ধৃত করা প্রয়োজন)। এবং ফাংশন এমনকি সহজ সংজ্ঞায়িত করা যেতে পারে: contains () { [[ "$1" =~ (^|[[:space:]])"$2"($|[[:space:]]) ]]; }
স্কোজিন

: list="aa bb xx cc ff"এবংx="aa bb"
ক্রিয়েটিভশিপ

হ্যালো. আমি বাশস্ক্রিপ্টের মৌলিক বিষয়গুলি শিখার চেষ্টা করছি এবং আমি জানতে চাইছিলাম আপনি কীভাবে তালিকার স্ট্রিংকে তালিকায় রাখতে পারেন, এবং সেই তালিকায় আপনি বিদ্যমান চেকটি করতে পারেন। আমি স্থান ব্যবহার করে আপনি বিভক্ত বুঝতে পারি তবে আমি সম্পূর্ণরূপে ভাবটি বুঝতে পারি নি। তুমি কি আমাকে Google এ কীওয়ার্ড প্রদান করতে পারেন এই মত প্রকাশের মৌলিক: $list =~ (^|[[:space:]])"$item"($|[[:space:]])। অথবা, আপনার যদি সময় থাকে তবে এই অভিব্যক্তিটির জন্য আপনার ব্যাখ্যা শুনে আমি আনন্দিত হব। দ্রষ্টব্য: আমার ধারণা এটি একটি রেজেক্স এক্সপ্রেশন (^ ইত্যাদি দিয়ে শুরু হয়) তবে আমি = = = এর অর্থ জানি না। সুতরাং আমি সামগ্রিক ব্যাখ্যাটি পছন্দ করব: পি
আলী ইলমাজ

28

আইএমএইচও-র সবচেয়ে সহজ সমাধান হ'ল একটি স্পেস সহ মূল স্ট্রিংটি পুনরায় সংযুক্ত করা এবং যুক্ত করা এবং একটি রেইজেক্সের বিরুদ্ধে পরীক্ষা করা [[ ]]

haystack='foo bar'
needle='bar'

if [[ " $haystack " =~ .*\ $needle\ .* ]]; then
    ...
fi

এটি একটি স্ট্রিংস হিসাবে যেমন সূঁচযুক্ত মানগুলি সহ মূল্যগুলিতে মিথ্যা ইতিবাচক হবে না, যেমন একটি খড়ের খালি দিয়ে foo barbaz

(ধারণাটি লজ্জাজনকভাবে চুরির ফর্ম জ্যাকুয়েরির- hasClass()ম্যাথোড)


4
বিভাজক স্থান না হলে, সমাধান আরও সুস্পষ্ট। এটি haystack="foo:bar"[[ ":$haystack:" = *:$needle:* ]]
রেইজেক্স ছাড়াইও করা যায়

25

কেমন

echo $list | grep -w $x

$?সিদ্ধান্ত নেওয়ার জন্য আপনি হয় আউটপুট বা উপরের লাইনটি পরীক্ষা করতে পারেন।

grep -w পুরো শব্দ নিদর্শন চেক।


1
"মান" বৈধ হলে এই "ভাল "টিকে বৈধতা দেবে না (যেমন তালিকায়) কারণ এটি এর সাবস্ট্রিং
অফির ফারচি

হ্যাঁ, এটি যেমন গ্রহণযোগ্য উত্তর দেয়। @glennjackman একটি কার্যনির্বাহী সমাধান দেয়।
f.ardelian

3
গ্রেপকে শান্ত রাখতে গ্রেপ-কিউ ব্যবহার করতে পারেন
আমির

এটি আংশিক ম্যাচগুলিও গ্রহণ করবে, যা ব্যবহারকারী যা চান তা নাও হতে পারে
কার্নিকার

3
@ কার্নিশার তখন ঠিক একটি মিলের জন্য
গ্রেপ

18

আপনি যদি ডাবল বন্ধনী ব্যবহার করেন তবে কেস স্টেটমেন্টের বাইরেও (* ওয়াইল্ডকার্ডস) ব্যবহার করতে পারেন:

string='My string';

if [[ $string == *My* ]]
then
echo "It's there!";
fi

3
সহজ এবং মার্জিত, +1
জোও পেরেইরা

14
"মাই" অন্য স্ট্রিংয়ের একটি স্ট্রিং, উদাহরণস্বরূপ স্ট্রিং = 'মাইকম্যান্ড স্ট্রিং' হলে এটি মিথ্যা পজিটিভ দেয়।
লুক লি

এটি লক্ষণীয় যে ওয়াইল্ডকার্ডগুলি ( *My*) অবশ্যই পরীক্ষার ডান পাশে থাকতে হবে।
জ্যাকব ভানাস

8

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

for item in $list
do
    case "$x" in
      item1|item2)
        echo "In the list"
        ;;
      not_an_item)
        echo "Error" >&2
        exit 1
        ;;
    esac
done

যদি রানটাইমটিতে তালিকাটি একটি অ্যারে ভেরিয়েবল হয় তবে অন্য উত্তরগুলির মধ্যে একটি সম্ভবত একটি ভাল ফিট।


7

লিপিটিতে যদি তালিকাটি স্থির করা থাকে তবে আমি নিম্নলিখিতটি সেরাটি পছন্দ করি:

validate() {
    grep -F -q -x "$1" <<EOF
item 1
item 2
item 3
EOF
}

তারপরে অনুমতি পেলে validate "$x"পরীক্ষার জন্য ব্যবহার করুন $x

আপনি যদি ওয়ান-লাইনার চান এবং আইটেমের নামগুলিতে হোয়াইটস্পেসের বিষয়ে চিন্তা না করেন তবে আপনি এটি ব্যবহার করতে পারেন ( -wপরিবর্তে বিজ্ঞপ্তি -x):

validate() { echo "11 22 33" | grep -F -q -w "$1"; }

মন্তব্য:

  • এটি পসিক্স shঅনুগত।
  • validateসাবস্ট্রিংগুলি গ্রহণ করে না ( -xযদি আপনি এটি চান তবে গ্রেপ করার বিকল্পটি সরিয়ে দিন )।
  • validateএর যুক্তিটিকে একটি স্থির স্ট্রিং হিসাবে ব্যাখ্যা করে, একটি নিয়মিত অভিব্যক্তি নয় ( -Fযদি আপনি এটি চান তবে গ্রেপ করার বিকল্পটি সরিয়ে দিন )।

ফাংশনটি ব্যবহারের জন্য নমুনা কোড:

for x in "item 1" "item2" "item 3" "3" "*"; do
    echo -n "'$x' is "
    validate "$x" && echo "valid" || echo "invalid"
done

6

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

declare -A list=( [one]=1 [two]=two [three]='any non-empty value' )
for value in one two three four
do
    echo -n "$value is "
    # a missing key expands to the null string, 
    # and we've set each interesting key to a non-empty value
    [[ -z "${list[$value]}" ]] && echo -n '*not* '
    echo "a member of ( ${!list[*]} )"
done

আউটপুট:

one is a member of ( one two three )
two is a member of ( one two three )
three is a member of ( one two three )
four is *not* a member of ( one two three )

2
... এবং আপনি যে প্রতিস্থাপন (এবং উপর নির্ভর করে না প্রক্রিয়া সহজ করতে echo -n) পরামিতি সৃজনশীল ব্যবহারের সঙ্গে: do is="${list[$value]+is }"; echo "$value ${is:-is *not* }a member of ( ${!list[*]} )"; done
টবি স্পিড

যদি আমার কাছে `list =" এক দুই তিনটি xyz ... "এর মতো একটি দীর্ঘ (দীর্ঘ) তালিকা থাকে তবে এই ধরণের অ্যারে তৈরি করার কোনও সহজ উপায় আছে?
অটো টুমিট

5

echo $LIST | xargs -n1 echo | grep $VALUEনীচের চিত্রিত হিসাবে ফর্মটি ব্যবহার করা আমার পক্ষে সহজ মনে হয়েছে :

LIST="ITEM1 ITEM2"
VALUE="ITEM1"
if [ -n "`echo $LIST | xargs -n1 echo | grep -e \"^$VALUE`$\" ]; then
    ...
fi

এটি একটি স্থান-বিচ্ছিন্ন তালিকার জন্য কাজ করে তবে আপনি এটিকে অন্য কোনও ডিলিমিটারের সাথে (যেমন :) অভিযোজিত করতে পারেন :

LIST="ITEM1:ITEM2"
VALUE="ITEM1"
if [ -n "`echo $LIST | sed 's|:|\\n|g' | grep -e \"^$VALUE`$\"`" ]; then
   ...
fi

নোট করুন যে "পরীক্ষার কাজ করার জন্য প্রয়োজনীয়।


এটি এতে না LIST="SOMEITEM1 ITEM2"থাকলেও ITEM1এটি সত্যে ফিরে আসবে
অফির ফারচি

ভাল ক্যাচ, আমি আংশিক ম্যাচ বাদ দিতে গ্রিপ-ই দিয়ে উদাহরণ আপডেট করেছি।
সাবাস্তিয়ান পিয়ের

আমি বিশ্বাস করি "যদি" বিবৃতি শেষে একটি অতিরিক্ত আছে। সঠিক ফর্মটি হ'ল: [-n "cho প্রতিধ্বনি $ তালিকা | xargs -n1 প্রতিধ্বনি | গ্রেপ -e \" ^ AL ভ্যালু $ \ "]
এলাদ তাবাক

3

ভেবেছিলাম আমি আমার সমাধানটি তালিকায় যুক্ত করব।

# Checks if element "$1" is in array "$2"
# @NOTE:
#   Be sure that array is passed in the form:
#       "${ARR[@]}"
elementIn () {
    # shopt -s nocasematch # Can be useful to disable case-matching
    local e
    for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
    return 1
}

# Usage:
list=(11 22 33)
item=22

if elementIn "$item" "${list[@]}"; then
    echo TRUE;
else
    echo FALSE
fi
# TRUE

item=44
elementIn $item "${list[@]}" && echo TRUE || echo FALSE
# FALSE

1

উদাহরণ

$ in_list super test me out
NO

$ in_list "super dude" test me out
NO

$ in_list "super dude" test me "super dude"
YES

# How to use in another script
if [ $(in_list $1 OPTION1 OPTION2) == "NO" ]
then
  echo "UNKNOWN type for param 1: Should be OPTION1 or OPTION2"
  exit;
fi

in_list

function show_help()
{
  IT=$(CAT <<EOF

  usage: SEARCH_FOR {ITEM1} {ITEM2} {ITEM3} ...

  e.g. 

  a b c d                    -> NO
  a b a d                    -> YES
  "test me" how "test me"    -> YES

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi

if [ "$#" -eq 0 ]; then
  show_help
fi

SEARCH_FOR=$1
shift;

for ITEM in "$@"
do
  if [ "$SEARCH_FOR" == "$ITEM" ]
  then
    echo "YES"
    exit;
  fi
done

echo "NO"

1

TARGET ভেরিয়েবলটি কেবল 'দ্বিপদী' বা 'রিগ্রেশন' হতে পারে, তবে নিম্নলিখিতগুলি নিম্নলিখিতটি করতে পারে:

# Check for modeling types known to this script
if [ $( echo "${TARGET}" | egrep -c "^(binomial|regression)$" ) -eq 0 ]; then
    echo "This scoring program can only handle 'binomial' and 'regression' methods now." >&2
    usage
fi

আপনি | এর সাথে আলাদা করে তালিকায় আরও স্ট্রিং যুক্ত করতে পারেন (পাইপ) অক্ষর।

Egrep ব্যবহারের সুবিধা হ'ল আপনি সহজেই কেস ইনসেভেটিভিটি যুক্ত করতে পারেন (-i), বা নিয়মিত অভিব্যক্তি সহ আরও জটিল পরিস্থিতিতে পরীক্ষা করতে পারেন।


1

এটি প্রায় আপনার মূল প্রস্তাব কিন্তু প্রায় 1-লাইনার। অন্যান্য বৈধ উত্তরের মতো জটিল নয়, এবং বাশ সংস্করণগুলির উপর নির্ভর করে না (পুরানো বাশার সাথে কাজ করতে পারে)।

OK=0 ; MP_FLAVOURS="vanilla lemon hazelnut straciatella"
for FLAV in $MP_FLAVOURS ; do [ $FLAV == $FLAVOR ] && { OK=1 ; break; } ; done
[ $OK -eq 0 ] && { echo "$FLAVOR not a valid value ($MP_FLAVOURS)" ; exit 1 ; }

আমার ধারণা আমার দৈর্ঘ্য এবং শৈলীতে উভয়ই এখনও উন্নত করা যেতে পারে।


0

যদি এটি দীর্ঘ না হয়; আপনি কেবল তাদের মত লজিকাল বা তুলনা বরাবর সাম্যের মধ্যে স্ট্রিং করতে পারেন।

if [ $ITEM == "item1" -o $ITEM == "item2" -o $ITEM == "item3" ]; then
    echo In the list
fi 

আমার এই সঠিক সমস্যাটি ছিল এবং উপরেরটি কুরুচিপূর্ণ হওয়ার সাথে সাথে অন্যান্য সাধারণীকরণের সমাধানগুলির চেয়ে এটি আরও স্পষ্ট।

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