বাশে হ্যাশ টেবিলগুলি কীভাবে সংজ্ঞায়িত করবেন?


556

পাইথন অভিধানের সমতুল্য তবে বাশে (ওএস এক্স এবং লিনাক্স জুড়ে কাজ করা উচিত)।


4
বাশ কি একটা অজগর / পার্ল স্ক্রিপ্ট চালাও ... এতো নমনীয়!
e2-e4

এক্সঅনশ ব্যবহার করার বিষয়টি বিবেচনা করুন (এটি গিথুবটিতে রয়েছে)।
অলিভার

উত্তর:


938

বাশ 4

বাশ 4 স্থানীয়ভাবে এই বৈশিষ্ট্যটি সমর্থন করে। আপনার স্ক্রিপ্টের হ্যাশব্যাংটি রয়েছে তা নিশ্চিত করুন #!/usr/bin/env bashবা #!/bin/bashআপনার ব্যবহার শেষ হচ্ছে না sh। নিশ্চিত হয়ে নিন যে আপনি হয় আপনার স্ক্রিপ্টটি সরাসরি চালাচ্ছেন, বা scriptদিয়ে সম্পাদন করুন bash script। (বাশের সাথে কোনও বাশ স্ক্রিপ্ট বাস্তবায়িত না হ'ল, এবং সত্যই হবে বিভ্রান্তিকর হবে!)

আপনি এটি করে একটি সহযোগী অ্যারে ঘোষণা করেন:

declare -A animals

আপনি এটিকে সাধারণ অ্যারে অ্যাসাইনমেন্ট অপারেটর ব্যবহার করে উপাদানগুলিতে পূরণ করতে পারেন। উদাহরণস্বরূপ, আপনি যদি একটি মানচিত্র রাখতে চান animal[sound(key)] = animal(value):

animals=( ["moo"]="cow" ["woof"]="dog")

বা এগুলি মার্জ করুন:

declare -A animals=( ["moo"]="cow" ["woof"]="dog")

তারপরে এগুলিকে সাধারণ অ্যারেগুলির মতোই ব্যবহার করুন। ব্যবহার

  • animals['key']='value' মান সেট করতে

  • "${animals[@]}" মান প্রসারিত করতে

  • "${!animals[@]}"(লক্ষ্য করুন !) কীগুলি প্রসারিত করতে

এগুলি উদ্ধৃত করতে ভুলবেন না:

echo "${animals[moo]}"
for sound in "${!animals[@]}"; do echo "$sound - ${animals[$sound]}"; done

বাশ 3

ব্যাশ 4 এর আগে আপনার কাছে অ্যা্যাসোসিয়েটিভ অ্যারে নেই। তাদের অনুকরণ করতে ব্যবহার করবেন নাeval । চলুন evalপ্লেগ মত, কারণ এটি হয় শেল স্ক্রিপ্টিং এর প্লেগ। সর্বাধিক গুরুত্বপূর্ণ কারণ হ'ল evalআপনার ডেটা এক্সিকিউটেবল কোড হিসাবে গণ্য করে (আরও অনেক কারণ রয়েছে)।

প্রথমে এবং সর্বাগ্রে : ব্যাশে উন্নীত করার বিষয়টি বিবেচনা করুন 4 এটি আপনার পক্ষে পুরো প্রক্রিয়াটিকে আরও সহজ করে তুলবে।

যদি কোনও কারণ আপনি আপগ্রেড করতে না পারেন তবে declareএটি একটি নিরাপদ বিকল্প। এটি বাশ কোডের মতো ডেটা মূল্যায়ন করে নাeval এবং যেমন এলোমেলো কোড ইঞ্জেকশনটিকে এত সহজে অনুমতি দেয় না।

আসুন ধারণাটি প্রবর্তন করে উত্তরটি প্রস্তুত করুন:

প্রথমত, নির্দেশনা

$ animals_moo=cow; sound=moo; i="animals_$sound"; echo "${!i}"
cow

দ্বিতীয়ত declare:

$ sound=moo; animal=cow; declare "animals_$sound=$animal"; echo "$animals_moo"
cow

তাদের একত্রিত করুন:

# Set a value:
declare "array_$index=$value"

# Get a value:
arrayGet() { 
    local array=$1 index=$2
    local i="${array}_$index"
    printf '%s' "${!i}"
}

আসুন এটি ব্যবহার করুন:

$ sound=moo
$ animal=cow
$ declare "animals_$sound=$animal"
$ arrayGet animals "$sound"
cow

দ্রষ্টব্য: declareএকটি ফাংশনে রাখা যাবে না। declareব্যাশ ফাংশনের অভ্যন্তরের যেকোন ব্যবহারের ফলে ভেরিয়েবলটি এটি স্থানীয়ভাবে তৈরি করে turns ফাংশনটি, যার অর্থ আমরা এটির সাথে বৈশ্বিক অ্যারে অ্যাক্সেস বা সংশোধন করতে পারি না। (ব্যাশ 4 এ আপনি ঘোষিত -g ব্যবহার করতে পারেন বৈশ্বিক ভেরিয়েবলগুলি ডিক্লেয়ার করতে - তবে ব্যাশ 4 এ, আপনি প্রথমে এসোসিয়েটিভ অ্যারেগুলি ব্যবহার করতে পারেন, এই কাজটি এড়িয়ে গিয়ে))

সারসংক্ষেপ:

  • ব্যাশ 4 এ আপগ্রেড করুন এবং declare -Aসহযোগী অ্যারেগুলির জন্য ব্যবহার করুন ।
  • declareআপনি আপগ্রেড করতে না পারলে বিকল্পটি ব্যবহার করুন ।
  • awkপরিবর্তে ব্যবহার বিবেচনা করুন এবং বিষয়টি পুরোপুরি এড়িয়ে চলুন।

1
@ রিচার্ড: সম্ভবতঃ আপনি আসলে বাশ ব্যবহার করছেন না। আপনার হ্যাশবাং কি বাশের পরিবর্তে শ, নাকি আপনি অন্যথায় আপনার কোডটি শ এর সাথে আহ্বান করছেন? আপনার ঘোষণার আগে এটিকে ডানদিক দিয়ে চেষ্টা করুন: "$ BASH_VERSION $ POSIXLY_CORRECT" প্রতিধ্বনি করুন, এটি আউটপুট হবে 4.xএবং হবে না y
lhunath

5
আপগ্রেড করা যায় না: বাশে স্ক্রিপ্টগুলি লেখার একমাত্র কারণ হ'ল "যে কোনও জায়গায় চালানো" বহনযোগ্যতা। সুতরাং বাশের কোনও অ-সর্বজনীন বৈশিষ্ট্যের উপর নির্ভর করা এই পদ্ধতির বাইরে চলে। যা লজ্জাজনক, কারণ তা না হলে এটি আমার পক্ষে একটি দুর্দান্ত সমাধান হত!
স্টিভ পিচার্স

3
এটি লজ্জাজনক যে ওএসএক্স 3 বাশকে ডিফল্ট হিসাবে এখনও এটি অনেক লোকের জন্য "ডিফল্ট" প্রতিনিধিত্ব করে। আমি ভেবেছিলাম শেলশক ভীতি তাদের প্রয়োজনীয় ধাক্কা হতে পারে তবে স্পষ্টতই তা হয়নি।
কেন

13
@ এটি একটি লাইসেন্সিং সমস্যা। ওএসএক্স-এ ব্যাশটি সর্বশেষতম নন-জিপিএলভি 3 লাইসেন্সযুক্ত বিল্ডে আটকে রয়েছে।
lhunath

2
... বা sudo port install bash, যারা (বুদ্ধিমানের সাথে, আইএমএইচও) সমস্ত ব্যবহারকারীদের জন্য প্রসেস-প্রসেসের সুবিধাযুক্ততা ছাড়াই লেখার জন্য PATH- এ ডিরেক্টরি তৈরি করতে রাজি নন।
চার্লস ডাফি

125

প্যারামিটারের বিকল্প রয়েছে, যদিও এটি আন-পিসিও হতে পারে ... ইন্ডিরিশনের মতো।

#!/bin/bash

# Array pretending to be a Pythonic dictionary
ARRAY=( "cow:moo"
        "dinosaur:roar"
        "bird:chirp"
        "bash:rock" )

for animal in "${ARRAY[@]}" ; do
    KEY="${animal%%:*}"
    VALUE="${animal##*:}"
    printf "%s likes to %s.\n" "$KEY" "$VALUE"
done

printf "%s is an extinct animal which likes to %s\n" "${ARRAY[1]%%:*}" "${ARRAY[1]##*:}"

বেস 4 উপায় অবশ্যই ভাল তবে আপনার যদি হ্যাকের প্রয়োজন হয় ... তবে কেবল একটি হ্যাকই করবে। আপনি অনুরূপ কৌশল সহ অ্যারে / হ্যাশ অনুসন্ধান করতে পারেন।


5
আমি VALUE=${animal#*:}মামলাটি রক্ষার জন্য এটি পরিবর্তন করব যেখানেARRAY[$x]="caesar:come:see:conquer"
গ্লেন জ্যাকম্যান

2
Keys {অ্যারে [@] around এর আশেপাশে ডাবল কোট স্থাপন করাও দরকারী, যেমনfor animal in "${ARRAY[@]}"; do
ডিগুইডাভিডে

1
কিন্তু দক্ষতা কি খুব কম নয়? আমি ও (এন * মি) ভাবছি যদি আপনি ও (এন) এর পরিবর্তে সঠিক হ্যাশম্যাপগুলি (ধ্রুবক সময় অনুসন্ধান, ও (1) একক কী এর) সাথে অন্য কীগুলির তালিকার সাথে তুলনা করতে চান O
কোডম্যানএক্স

1
পার্ল, পাইথন বা এমনকি ব্যাশের পটভূমির লোকদের জন্য দক্ষতা সম্পর্কে ধারণা / পাঠের দক্ষতা সম্পর্কে কম ধারণা 4 4. আপনাকে একই ধরণের লেখায় মঞ্জুরি দেয়।
বুবনফ

1
@CoDEmanX: এটা হল হ্যাক , একটি চালাক এবং মার্জিত কিন্তু এখনও প্রাথমিক কার্যসংক্রান্ত সাহায্যের দরিদ্র আত্মার এখনও ব্যাশ 3.x. সঙ্গে 2007 সালে আটকে আপনি এই জাতীয় কোনও সহজ কোডটিতে "সঠিক হ্যাশম্যাপস" বা দক্ষতার বিবেচনা আশা করতে পারবেন না।
MestreLion

85

এটি আমি এখানে খুঁজছিলাম:

declare -A hashmap
hashmap["key"]="value"
hashmap["key2"]="value2"
echo "${hashmap["key"]}"
for key in ${!hashmap[@]}; do echo $key; done
for value in ${hashmap[@]}; do echo $value; done
echo hashmap has ${#hashmap[@]} elements

এটি আমার পক্ষে বাশ ৪.১.৫ নিয়ে কাজ করে নি:

animals=( ["moo"]="cow" )

2
দ্রষ্টব্য,
মানটিতে

6
হ্যাশম্যাপ ["কী"] = "মান" সিনট্যাক্সের জন্য আপভোট যা আমিও অন্যথায় দুর্দান্ত গ্রহণযোগ্য উত্তর থেকে অনুপস্থিত পেয়েছি।
thomanski

@ রুবো key। কী না, এটি একাধিক কী যুক্ত করে। কোন উপায় এই workaround?
জিভেরাস

25

আপনি hp () / hget () ইন্টারফেসটি আরও সংশোধন করতে পারেন যাতে আপনি নীচে হ্যাশগুলির নাম দিয়েছেন:

hput() {
    eval "$1""$2"='$3'
}

hget() {
    eval echo '${'"$1$2"'#hash}'
}

এবং তারপর

hput capitals France Paris
hput capitals Netherlands Amsterdam
hput capitals Spain Madrid
echo `hget capitals France` and `hget capitals Netherlands` and `hget capitals Spain`

এটি আপনাকে অন্যান্য মানচিত্র সংজ্ঞায়িত করতে দেয় যা দ্বন্দ্ব নয় (উদাহরণস্বরূপ, 'আরসি ক্যাপিটালস' যা রাজধানী শহর দ্বারা দেশ অনুসন্ধান করে)। তবে, যেভাবেই হোক না কেন, আমি মনে করি আপনি এটি দেখতে পাবেন যে এটি খুব ভয়ঙ্কর, পারফরম্যান্স ভিত্তিক।

আপনি যদি সত্যিই দ্রুত হ্যাশ লুক করতে চান তবে একটি ভয়ঙ্কর, ভয়ঙ্কর হ্যাক রয়েছে যা প্রকৃতপক্ষে খুব ভালভাবে কাজ করে। এটি হ'ল: আপনার কী / মানগুলি অস্থায়ী ফাইলে লিখুন, প্রতি লাইনে একটি করে, তারপরে 'গ্রেপ "^ $ কী"' ব্যবহার করুন, কাটা বা জাজক বা সেডযুক্ত পাইপগুলি ব্যবহার করে বা মানগুলি পুনরুদ্ধার করতে যা কিছু আছে।

যেমনটি আমি বলেছিলাম, এটি ভয়ানক শোনায়, এবং মনে হচ্ছে এটি ধীরে ধীরে হওয়া উচিত এবং সমস্ত ধরণের অপ্রয়োজনীয় আইও করা উচিত, তবে বাস্তবে এটি খুব দ্রুত (ডিস্ক ক্যাশে দুর্দান্ত, তাই না?) এমনকি খুব বড় হ্যাশের জন্যও টেবিল। আপনাকে কীগুলি স্বতন্ত্রতা নিজেকে প্রয়োগ করতে হবে, ইত্যাদি you যদি আপনার কেবল কয়েকশত এন্ট্রি থাকে তবে আউটপুট ফাইল / গ্রেপ কম্বো বেশ খানিকটা দ্রুত গতিতে চলেছে - আমার অভিজ্ঞতায় কয়েকগুণ দ্রুত। এটি স্মৃতিশক্তিও কম খায়।

এটি করার একটি উপায় এখানে:

hinit() {
    rm -f /tmp/hashmap.$1
}

hput() {
    echo "$2 $3" >> /tmp/hashmap.$1
}

hget() {
    grep "^$2 " /tmp/hashmap.$1 | awk '{ print $2 };'
}

hinit capitals
hput capitals France Paris
hput capitals Netherlands Amsterdam
hput capitals Spain Madrid

echo `hget capitals France` and `hget capitals Netherlands` and `hget capitals Spain`

1
গ্রেট! এমনকি আপনি এটির পুনরাবৃত্তিও করতে পারেন: আমি ইন comp (কমপেন-এ ভেরিয়েবল ক্যাপিটল) এর জন্য; do hget "" i "" "সম্পন্ন করুন
zhaorufei

22

কেবল ফাইল সিস্টেমটি ব্যবহার করুন

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

হ্যাশটেবল সৃষ্টি

hashtable=$(mktemp -d)

একটি উপাদান যুক্ত করুন

echo $value > $hashtable/$key

একটি উপাদান পড়ুন

value=$(< $hashtable/$key)

কর্মক্ষমতা

অবশ্যই, এটি ধীর, কিন্তু এটি ধীর নয়। আমি এটি আমার মেশিনে একটি এসএসডি এবং বিটিআরএফ দিয়ে পরীক্ষা করেছি এবং এটি প্রতি সেকেন্ডে প্রায় 3000 উপাদান পড়তে / লেখায়


1
বাশের কোন সংস্করণ সমর্থন করে mkdir -d? (উবুন্টু ১৪ এ mkdir /run/shm/foomkdir /tmp/foo
4..৩

1
সম্ভবত mktemp -dপরিবর্তে বোঝানো হয়েছে?
রিড এলিস

2
কৌতুহল কি $value=$(< $hashtable/$key)এবং এর মধ্যে পার্থক্য কি value=$(< $hashtable/$key)? ধন্যবাদ!
হেলিন ওয়াং

1
"এটি আমার মেশিনে পরীক্ষা করা হয়েছে" এটি আপনার এসএসডি দিয়ে কোনও গর্ত পোড়ানোর দুর্দান্ত উপায় বলে মনে হচ্ছে। সমস্ত লিনাক্স ডিস্ট্রোজ ডিফল্টরূপে tmpf ব্যবহার করে না।
kirbyfan64sos

আমি প্রায় 50000 হ্যাশ প্রক্রিয়াজাত করছি। পার্ল এবং পিএইচপি এটি 1/2 সেকেন্ডের নীচে চুল দেয়। 1 সেকেন্ডে নোড এবং কিছু। এফএস বিকল্পটি ধীর মনে হচ্ছে। তবে, আমরা কি নিশ্চিত করতে পারি যে কোনও রকমে কেবল ফাইলগুলি র‍্যামে রয়েছে?
রল্ফ

14
hput () {
  eval hash"$1"='$2'
}

hget () {
  eval echo '${hash'"$1"'#hash}'
}
hput France Paris
hput Netherlands Amsterdam
hput Spain Madrid
echo `hget France` and `hget Netherlands` and `hget Spain`

$ sh hash.sh
Paris and Amsterdam and Madrid

31
দীর্ঘশ্বাস, এটিকে অপ্রয়োজনীয়ভাবে অপমানজনক বলে মনে হচ্ছে এবং এটি যাইহোক ভুল। কেউ হ্যাশ টেবিলের সাহসী অবস্থায় ইনপুট বৈধতা, পালাবার বা এনকোডিং (দেখুন, আমি আসলে জানি না) রাখি না, বরং একটি মোড়কে এবং ইনপুট পরে যত তাড়াতাড়ি সম্ভব।
ডিজিটালরোস

@ ডিজিটালরোস আপনি কী ব্যাখ্যা করতে পারেন যে ইভা'ল cho {{হ্যাশ '"$ 1"' # হ্যাশ} 'তে # হ্যাশ ব্যবহার কী । আমার জন্য এটি আমার কাছে মন্তব্য হিসাবে মনে হয় তবে এর চেয়ে বেশি নয়। # হ্যাশ এর কি এখানে কোন বিশেষ অর্থ আছে?
সঞ্জয়

@Sanjay ${var#start}টেক্সট সরিয়ে ফেলা শুরু পরিবর্তনশীল সঞ্চিত মান শুরু থেকে Var
jpaugh

11

একটি সমাধান builtin ব্যাশ ব্যবহার করার কথা বিবেচনা পঠিত হিসাবে একটি ufw ফায়ারওয়াল স্ক্রিপ্ট যে অনুসরণ করে থেকে কোড স্নিপেট মধ্যে সচিত্র। এই পদ্ধতির পছন্দসই হিসাবে অনেক সীমিত ক্ষেত্রের সেটগুলি (কেবল 2 নয়) ব্যবহার করার সুবিধা রয়েছে। আমরা ব্যবহার করেছি | ডিলিমিটার কারণ পোর্ট রেঞ্জ স্পেসিফায়ারগুলির জন্য একটি কোলোন প্রয়োজন হতে পারে, যেমন 6001: 6010

#!/usr/bin/env bash

readonly connections=(       
                            '192.168.1.4/24|tcp|22'
                            '192.168.1.4/24|tcp|53'
                            '192.168.1.4/24|tcp|80'
                            '192.168.1.4/24|tcp|139'
                            '192.168.1.4/24|tcp|443'
                            '192.168.1.4/24|tcp|445'
                            '192.168.1.4/24|tcp|631'
                            '192.168.1.4/24|tcp|5901'
                            '192.168.1.4/24|tcp|6566'
)

function set_connections(){
    local range proto port
    for fields in ${connections[@]}
    do
            IFS=$'|' read -r range proto port <<< "$fields"
            ufw allow from "$range" proto "$proto" to any port "$port"
    done
}

set_connections

2
@ চর্লিমার্টিন: পঠন একটি খুব শক্তিশালী বৈশিষ্ট্য এবং এটি বহু ব্যাশ প্রোগ্রামাররা স্বল্প-ব্যবহৃত। এটি লিসপ-এর মতো তালিকা প্রক্রিয়াকরণের কমপ্যাক্ট ফর্মগুলিকে অনুমতি দেয় । উদাহরণস্বরূপ, উপরোক্ত উদাহরণে আমরা বন্ধ শুধুমাত্র প্রথম উপাদান (যেমন একটি অনুরূপ ধারণা থেকে স্ট্রিপ পারে এবং বাকি রাখা প্রথম এবং বিশ্রাম পাতার মর্মর মধ্যে) করে:IFS=$'|' read -r first rest <<< "$fields"
AsymLabs

6

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

  1. 2 টি পৃথককারী চয়ন করুন যা আপনি কী এবং মানগুলিতে ব্যবহার করবেন না (যেমন ',' এবং ':')
  2. আপনার মানচিত্রটি স্ট্রিং হিসাবে লিখুন (বিভাজকটি ',' এবং শুরুতে এবং শেষেও নোট করুন)

    animals=",moo:cow,woof:dog,"
  3. মানগুলি নিষ্কাশন করতে একটি রেজেক্স ব্যবহার করুন

    get_animal {
        echo "$(expr "$animals" : ".*,$1:\([^,]*\),.*")"
    }
  4. আইটেমগুলি তালিকাবদ্ধ করতে স্ট্রিংটি বিভক্ত করুন

    get_animal_items {
        arr=$(echo "${animals:1:${#animals}-2}" | tr "," "\n")
        for i in $arr
        do
            value="${i##*:}"
            key="${i%%:*}"
            echo "${value} likes to $key"
        done
    }

এখন আপনি এটি ব্যবহার করতে পারেন:

$ animal = get_animal "moo"
cow
$ get_animal_items
cow likes to moo
dog likes to woof

5

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

hinit() {
    rm -rf /tmp/hashmap.$1
    mkdir -p /tmp/hashmap.$1
}

hput() {
    printf "$3" > /tmp/hashmap.$1/$2
}

hget() {
    cat /tmp/hashmap.$1/$2
}

hkeys() {
    ls -1 /tmp/hashmap.$1
}

hdestroy() {
    rm -rf /tmp/hashmap.$1
}

hinit ids

for (( i = 0; i < 10000; i++ )); do
    hput ids "key$i" "value$i"
done

for (( i = 0; i < 10000; i++ )); do
    printf '%s\n' $(hget ids "key$i") > /dev/null
done

hdestroy ids

এটি আমার পরীক্ষাগুলিতে আরও কিছুটা ভাল অভিনয় করে।

$ time bash hash.sh 
real    0m46.500s
user    0m16.767s
sys     0m51.473s

$ time bash dirhash.sh 
real    0m35.875s
user    0m8.002s
sys     0m24.666s

শুধু ভেবেছি আমি পিচ করব। চিয়ার্স!

সম্পাদনা করুন: hdestroy যুক্ত করা ()


3

দুটি জিনিস, আপনি / dev / shm (redhat) ব্যবহার করে যে কোনও কার্নেল ২.6-তে / tmp এর পরিবর্তে মেমরি ব্যবহার করতে পারেন অন্যান্য ডিস্ট্রোগুলি ভিন্ন হতে পারে। নীচে নীচে পড়া ব্যবহার করে হেইজেট পুনরায় প্রয়োগ করা যেতে পারে:

function hget {

  while read key idx
  do
    if [ $key = $2 ]
    then
      echo $idx
      return
    fi
  done < /dev/shm/hashmap.$1
}

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

Grep / awk:

hget() {
    grep "^$2 " /dev/shm/hashmap.$1 | awk '{ print $2 };'
}

$ time echo $(hget FD oracle)
3

real    0m0.011s
user    0m0.002s
sys     0m0.013s

পঠন / echo:

$ time echo $(hget FD oracle)
3

real    0m0.004s
user    0m0.000s
sys     0m0.004s

একাধিক অনুরোধে আমি কখনই কম দেখিনি 50% উন্নতি। ব্যবহারের কারণে এগুলি সমস্ত কাঁটা ওভার কাঁটাতে দায়ী করা যেতে পারে /dev/shm


3

একজন সহকর্মী এই থ্রেডটির স্রেফ উল্লেখ করেছেন। আমি বাশের মধ্যে হ্যাশ টেবিলগুলি স্বাধীনভাবে প্রয়োগ করেছি এবং এটি সংস্করণ ৪ এর উপর নির্ভর করে না, ২০১০ সালের মার্চ মাসে আমার একটি ব্লগ পোস্ট থেকে (এখানে উত্তরগুলির কিছু আগে ...) বাশ-এর ​​হ্যাশ টেবিল শিরোনাম :

আমি পূর্বে ব্যবহার করা cksumহ্যাশ করার কিন্তু যেহেতু অনুবাদ জাভার স্ট্রিং হ্যাশকোড নেটিভ ব্যাশ / zsh করতে।

# Here's the hashing function
ht() {
  local h=0 i
  for (( i=0; i < ${#1}; i++ )); do
    let "h=( (h<<5) - h ) + $(printf %d \'${1:$i:1})"
    let "h |= h"
  done
  printf "$h"
}

# Example:

myhash[`ht foo bar`]="a value"
myhash[`ht baz baf`]="b value"

echo ${myhash[`ht baz baf`]} # "b value"
echo ${myhash[@]} # "a value b value" though perhaps reversed
echo ${#myhash[@]} # "2" - there are two values (note, zsh doesn't count right)

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


উত্তরের লিঙ্কটি ভীতিজনক! আপনি যদি এটি ক্লিক করেন তবে আপনি পুনর্নির্দেশের লুপে আটকে আছেন। আপডেট করুন.
রাকিব

1
@ মোহাম্মদরাকিবআমিন - হ্যাঁ, আমার ওয়েবসাইটটি নিচে রয়েছে এবং আমি সন্দেহ করছি যে আমি আমার ব্লগটি পুনরুত্থিত করব। আমি উপরের লিঙ্কটি সংরক্ষণাগারিত সংস্করণে আপডেট করেছি। আপনার আগ্রহের জন্য ধন্যবাদ!
অ্যাডাম কাটজ

2

ব্যাশ 4 এর আগে ব্যাশে এসোসিয়েটিভ অ্যারেগুলি ব্যবহার করার কোনও ভাল উপায় নেই। আপনার সেরা বেট হ'ল এমন ব্যাখ্যামূলক ভাষা ব্যবহার করা যা সত্যিকারের মতো এডকের মতো সমর্থন করে। অন্যদিকে, বাশ 4 করে তাদের সমর্থন।

ব্যাশ 3 এর কম ভাল উপায়গুলির জন্য , এখানে সাহায্যের তুলনায় আরও একটি রেফারেন্স দেওয়া হয়েছে: http://mywiki.wooledge.org/BashFAQ/006


2

3 টি সমাধান:

কিছু উত্তর পড়ার সাথে সাথে আমি একটি দ্রুত সামান্য ফাংশন একসাথে রেখেছি যাতে আমি অন্যদের সহায়তা করতে পারে এমন ফিরিয়ে দিতে চাই।

# Define a hash like this
MYHASH=("firstName:Milan"
        "lastName:Adamovsky")

# Function to get value by key
getHashKey()
 {
  declare -a hash=("${!1}")
  local key
  local lookup=$2

  for key in "${hash[@]}" ; do
   KEY=${key%%:*}
   VALUE=${key#*:}
   if [[ $KEY == $lookup ]]
   then
    echo $VALUE
   fi
  done
 }

# Function to get a list of all keys
getHashKeys()
 {
  declare -a hash=("${!1}")
  local KEY
  local VALUE
  local key
  local lookup=$2

  for key in "${hash[@]}" ; do
   KEY=${key%%:*}
   VALUE=${key#*:}
   keys+="${KEY} "
  done

  echo $keys
 }

# Here we want to get the value of 'lastName'
echo $(getHashKey MYHASH[@] "lastName")


# Here we want to get all keys
echo $(getHashKeys MYHASH[@])

আমি মনে করি এটি একটি সুন্দর ঝরঝরে স্নিপেট। এটি সামান্য পরিচ্ছন্নতা ব্যবহার করতে পারে (যদিও খুব বেশি নয়)। আমার সংস্করণে, আমি 'কী'র নাম' জোড় 'রেখেছি এবং কে এবং ভ্যালু ছোট হাতের অক্ষর তৈরি করেছি (কারণ আমি যখন ভেরিয়েবলগুলি এক্সপোর্ট করা হয় তখন বড় হাতের ব্যবহার করি)। আমি getHashKey এর নাম getHashValue এ রেখেছি এবং কী এবং মান উভয়কেই স্থানীয় করে তুললাম (কখনও কখনও আপনি চাইবেন যে সেগুলি স্থানীয় না হয়)। GetHashKeys এ, আমি কোনও মূল্যকে বরাদ্দ করি না। আমি পৃথক হওয়ার জন্য সেমিকোলন ব্যবহার করি, যেহেতু আমার মানগুলি ইউআরএল।

0

আমি ব্যাশ 4 উপায়ও ব্যবহার করেছি তবে আমি বাগ খুঁজে পাই এবং বিরক্তিকর।

আমার ডায়নামিকভাবে এসোসিয়েটিভ অ্যারে সামগ্রী আপডেট করার দরকার ছিল তাই আমি এইভাবে ব্যবহার করেছি:

for instanceId in $instanceList
do
   aws cloudwatch describe-alarms --output json --alarm-name-prefix $instanceId| jq '.["MetricAlarms"][].StateValue'| xargs | grep -E 'ALARM|INSUFFICIENT_DATA'
   [ $? -eq 0 ] && statusCheck+=([$instanceId]="checkKO") || statusCheck+=([$instanceId]="allCheckOk"
done

আমি খুঁজে পেয়েছি যে বাশ সঙ্গে 4.3.11 ডিকটিতে বিদ্যমান কীটিতে সংযোজন করার ফলে ইতিমধ্যে উপস্থিত থাকলে মান সংযোজন করতে পারে। সুতরাং উদাহরণস্বরূপ কিছু পুনরাবৃত্তি করার পরে মানটির বিষয়বস্তু ছিল "চেককোচেককঅল চেকক" এবং এটি ভাল ছিল না।

4.3.39 বাশ নিয়ে কোনও সমস্যা নেই যেখানে একটি বিদ্যমান কী সংযোজন করার অর্থ ইতিমধ্যে উপস্থিত থাকলে অ্যাকুয়ালের মানকে সাবস্টিচার করা।

আমি স্রেফ সাফ করার / স্থিতি ঘোষণার সমাধান করেছি সাইকেলের আগে চেক অ্যাসোসিয়েটিভ অ্যারে:

unset statusCheck; declare -A statusCheck

-1

আমি গতিশীল ভেরিয়েবলগুলি ব্যবহার করে ব্যাশ 3 এ হ্যাশম্যাপগুলি তৈরি করি। আমি ব্যাখ্যা করেছি যে এটি আমার উত্তরটিতে কীভাবে কাজ করে: শেল স্ক্রিপ্টগুলিতে সহযোগী অ্যারেগুলি ys

এছাড়াও আপনি শেল_ম্যাপটিতে একবার দেখতে পারেন , যা ব্যাশ 3-এ তৈরি করা হ্যাশম্যাপ বাস্তবায়ন।

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