ব্যাশে টিপলস লুপ?


89

ব্যাশে টিপলস থেকে লুপ করা কি সম্ভব?

উদাহরণ হিসাবে, নিম্নলিখিতটি যদি কাজ করে তবে তা দুর্দান্ত হবে:

for (i,j) in ((c,3), (e,5)); do echo "$i and $j"; done

এমন কোনও কর্মপরীক্ষা রয়েছে যা আমাকে কোনওভাবে টিপলস থেকে লুপ করতে দেয়?


4
অজগর ব্যাকগ্রাউন্ড থেকে আসা এটি সত্যিই একটি খুব দরকারী প্রশ্ন!
জন জিয়াং

4
এই চার বছর পরে তাকিয়ে আমি অবাক করি যদি এখনও এটি করার আরও ভাল উপায় না থাকে। ঈশ্বর.
গিজমো

প্রায় 8 বছর পরে আমি আরও ভাবলাম যে এটি করার আরও ভাল উপায় আর নেই। তবে এই 2018 এর উত্তরটি আমার কাছে বেশ ভাল দেখাচ্ছে: stackoverflow.com/a/52228219/463994
মাউন্টেনএক্স

উত্তর:


87
$ for i in c,3 e,5; do IFS=","; set -- $i; echo $1 and $2; done
c and 3
e and 5

set(থেকে man builtins) এর এই ব্যবহার সম্পর্কে :

বিকল্প প্রক্রিয়াজাতকরণের পরে থাকা যে কোনও আর্গুমেন্টকে অবস্থানগত পরামিতিগুলির মান হিসাবে বিবেচনা করা হয় এবং ক্রমে $ 1, $ 2, ... $ n এ নির্ধারিত হয়

IFS=","ক্ষেত্র বিভাজক তাই সেট করে $iমধ্যে ভাগ পরার $1এবং $2সঠিকভাবে।

এই ব্লগ মাধ্যমে ।

সম্পাদনা করুন: আরও সঠিক সংস্করণ, @ স্ল্যাকডিয়ামামন্ডের পরামর্শ অনুসারে:

$ OLDIFS=$IFS; IFS=','; for i in c,3 e,5; do set -- $i; echo $1 and $2; done; IFS=$OLDIFS
c and 3
e and 5

7
ভাল - কেবল নির্দেশ করতে চাইছে IFSসংরক্ষণ করা উচিত এবং যদি এটি কমান্ড লাইনে চালিত হয় তবে তার মূল মানটিতে পুনরায় সেট করা উচিত। এছাড়াও, IFSপ্রতিটি পুনরাবৃত্তির পরিবর্তে লুপটি চালানোর আগে নতুনটি একবার সেট করা যায়।
Eggxactly

4
যদি কোনও হাইফেন দিয়ে শুরু হয় তবে এটি আরও নিরাপদset -- $i
গ্লেন জ্যাকম্যান

4
সংরক্ষণ করার পরিবর্তে IFS, শুধুমাত্র এটি সেট setকমান্ড প্রয়োগ করুন: for i in c,3 e,5; do IFS="," set -- $i; echo $1 and $2; done। দয়া করে আপনার উত্তরটি সম্পাদনা করুন: সমস্ত পাঠক যদি তালিকাবদ্ধ সমাধানগুলির মধ্যে একটি মাত্র চয়ন করেন তবে সম্পূর্ণ বিকাশের ইতিহাস পড়ার কোনও ধারণা নেই। এই দুর্দান্ত কৌশলটির জন্য ধন্যবাদ!
সিএফআই

যদি আমি সম্পাদিত সংস্করণ হিসাবে এবং এর পরিবর্তে ঘোষণা করি tuples="a,1 b,2 c,3"এবং রাখিIFS=','c,3 e,5 ব্যবহারের$tuples এটি মোটে ভাল মুদ্রণ করে না। তবে এর পরিবর্তে যদি আমি লুপের জন্য কীওয়ার্ডের IFS=','পরে রাখি তবে লিটারেরাল মানগুলি doব্যবহার করার সময় এটি ভাল কাজ করে $tuples। শুধু ভেবেছি এটি বলার অপেক্ষা রাখে না।
সাইমনলবিসি

@ সিমোনলবিসি কারণ লুপটি IFSপুনরাবৃত্তিগুলি বিভক্ত করতে ব্যবহার করে। অর্থাত্ যদি আপনি কোনও অ্যারের উপরে লুপ করেন arr=("c,3" "e,5")এবং রাখেনIFS তবে এর মান $iঠিক হবে cএবং e, এটি বিভক্ত হয়ে যাবে 3এবং 5তাই setসঠিকভাবে বিশ্লেষণ $iকরবে না কারণ পার্স করার মতো কিছু থাকবে না। এর অর্থ হ'ল পুনরাবৃত্তি করার মানগুলি যদি ইনলাইন করা না যায় তবে লুপটির IFSভিতরে রাখা উচিত এবং বাইরের মানটি পরিবর্তনশীলটির পুনরাবৃত্তির জন্য উদ্দেশ্যে বিভাজককে সম্মান করে। $tuplesএটির ক্ষেত্রে এটি সাধারণভাবে হওয়া উচিত IFS=যা ডিফল্ট এবং সাদা স্থানের উপরে বিভক্ত হয়।
অপরিচিত

26

আমি বিশ্বাস করি যে এই সমাধানটি জমা দেওয়া অন্যদের চেয়ে কিছুটা ক্লিনার, এই ব্যাশ শৈলীর নির্দেশিকায় h / t কীভাবে পাঠ্যকে একটি ডিলিমিটারে স্ট্রিংগুলি বিভক্ত করতে এবং পৃথক ভেরিয়েবলগুলিতে নির্ধারণের জন্য ব্যবহার করা যেতে পারে তা বোঝানোর জন্য b

for i in c,3 e,5; do 
    IFS=',' read item1 item2 <<< "${i}"
    echo "${item1}" and "${item2}"
done

20

@ এডুয়ার্ডো-আইভানেকের দেওয়া / পুনরায় সেট না করে দেওয়া উত্তরের উপর ভিত্তি করে IFS, কেউ কেবল তা করতে পারে:

for i in "c 3" "e 5"
do
    set -- $i
    echo $1 and $2
done

আউটপুট:

c and 3
e and 5

এই পদ্ধতিটি আমার কাছে গৃহীত এবং সর্বাধিক উন্নত পদ্ধতির চেয়ে অনেক সহজ বলে মনে হচ্ছে। @ এডুয়ার্ডো ইভানেকের পরামর্শ অনুসারে এইভাবে এটি না করার কোনও কারণ আছে কি?
স্পাররা

@ স্পুরার এই উত্তরটি 6 বছর এবং আরও সাম্প্রতিক, এবং এর উপর ভিত্তি করে। যেখানে Creditণ আছে সেখানে Creditণ।
দিয়েগো

4
@ ডিগো আমি এটি সম্পর্কে অবহিত। এটি সুস্পষ্টভাবে উত্তরে লেখা আছে। আমি জিজ্ঞাসা করছিলাম গ্রহণযোগ্য উত্তরের উপর এই পদ্ধতির ব্যবহার না করার কোনও কারণ আছে কিনা?
স্পুরা

4
@ স্পুরা আপনি যদি এডুয়ার্ডোর উত্তরটি ব্যবহার করতে চান তবে ডিফল্ট বিভাজক (স্থান, ট্যাব বা নিউলাইন) কোনও কারণে আপনার জন্য কাজ না করলে ( bash.cyberciti.biz/guide/$IFS )
ডিয়েগো

13

সহযোগী অ্যারে (অভিধান / হ্যাশম্যাপ হিসাবে পরিচিত) ব্যবহার করুন:

declare -A pairs=(
  [c]=3
  [e]=5
)
for key in "${!pairs[@]}"; do
  value="${pairs[$key]}"
  echo "key is $key and value is $value"
done

Bash4.0 + এর জন্য কাজ করে।


আপনার যদি জোড়াগুলির পরিবর্তে ট্রিপলগুলির প্রয়োজন হয় তবে আপনি আরও সাধারণ পদ্ধতির ব্যবহার করতে পারেন:

animals=(dog cat mouse)
declare -A sound=(
  [dog]=barks
  [cat]=purrs
  [mouse]=cheeps
)
declare -A size=(
  [dog]=big
  [cat]=medium
  [mouse]=small
)
for animal in "${animals[@]}"; do
  echo "$animal ${sound[$animal]} and it is ${size[$animal]}"
done

এফওয়াইআই, এটি ম্যাকের সাথে আমার জন্য কাজ করেনি GNU bash, version 4.4.23(1)-release-(x86_64-apple-darwin17.5.0), যা মেশানো মাধ্যমে ইনস্টল করা হয়েছিল, তাই ওয়াইএমএমভি।
ডেভিড

তবে GNU bash, version 4.3.11(1)-release-(x86_64-pc-linux-gnu)উবুন্টু থেকে 14.04 ডকের পাত্রে এটি কাজ করেছিল।
ডেভিড

বাশের পুরানো সংস্করণগুলির মতো মনে হচ্ছে বা এই বৈশিষ্ট্যটিকে সমর্থন করে না সূচক বেসিংয়ের কাজ করে? যেখানে কীটি স্ট্রিংয়ের পরিবর্তে একটি সংখ্যা। tldp.org/LDP/abs/html/declareref.html , এবং এর পরিবর্তে -Aআমাদের রয়েছে -a
ডেভিড

ডেভিড, তাই মনে হচ্ছে। আমি মনে করি আপনি তখন "সাহচর্যতা" পেতে অ্যারে সূচকগুলি চেষ্টা করতে পারেন। মত declare -a indices=(1 2 3); declare -a sound=(barks purrs cheeps); declare -a size=(big medium small)ইত্যাদি এখনও টার্মিনালে এটি চেষ্টা করেন নি, তবে আমার মনে হয় এটি কাজ করা উচিত।
ভ্যাসিলিনোভিকভ

7
c=('a' 'c')
n=(3    4 )

for i in $(seq 0 $((${#c[*]}-1)))
do
    echo ${c[i]} ${n[i]}
done

কখনও কখনও আরও সহজ হতে পারে।

uglyঅংশটি ব্যাখ্যা করার জন্য , মন্তব্যে উল্লিখিত:

SeQ 0 2 তাই এই উদাহরণে আউটপুট জন্য, সংখ্যা ক্রম 0 থেকে 1 2. $ (cmd কমান্ড) কমান্ড প্রতিকল্পন হয় উৎপন্ন seq 0 2, যা সংখ্যা ক্রম। তবে উপরের আবদ্ধটি $((${#c[*]}-1))কী?

$ ((পারছেন)) গাণিতিক সম্প্রসারণ, তাই $ ((3 + 4)) হয় 7 ইত্যাদি আমাদের অভিব্যক্তি ${#c[*]}-1যদি আমরা জানি কি, 1. সুন্দর সহজ -, তাই কিছু ${#c[*]}নেই।

c একটি অ্যারে, সি [*] হ'ল পুরো অ্যারে, $ {# সি [*]। অ্যারের আকার যা আমাদের ক্ষেত্রে 2। এখন আমরা সবকিছু ফিরে পাকানো: for i in $(seq 0 $((${#c[*]}-1)))হয় for i in $(seq 0 $((2-1)))হয় for i in $(seq 0 1)হয় for i in 0 1। কারণ অ্যারের শেষ উপাদানটির একটি সূচক রয়েছে যা অ্যারের দৈর্ঘ্য - 1 1


4
আপনাকে যা করতে হবেfor i in $(seq 0 $(($#c[*]}-1))); do [...]
reox

4
বাহ, এটি "আজ আমি দেখেছি সালিশী চরিত্রের উগলিস্ট গুচ্ছ" পুরস্কার জিতেছে। এই ঘৃণাটি ঠিক কী করে তা বোঝানোর জন্য কেউ যত্নশীল? আমি হ্যাশ সাইন এ হারিয়ে
গিয়েছি

4
@ কোনিয়িক: ব্যাখ্যা যুক্ত হয়েছে।
ব্যবহারকারীর অজানা

"নিউ-পার্ল: দ্য রিভেঞ্জ" আমি মনে করি এটি আসলে পার্লের মাধ্যমে আরও পরিষ্কার হবে। :-)
বাজ মোসচেটি


3

জিএনইউ সমান্তরাল ব্যবহার:

parallel echo {1} and {2} ::: c e :::+ 3 5

বা:

parallel -N2 echo {1} and {2} ::: c 3 e 5

বা:

parallel --colsep , echo {1} and {2} ::: c,3 e,5

4
এই জন্য কোন ভালবাসা? ভাল হয়েছে আমাকে নিষ্ক্রিয়তা পরাস্ত এবং ইনস্টলgnu parallel
StephenBoesch

4
brew install parallel
স্টিফেনবোশ

2

printfপ্রক্রিয়া প্রতিস্থাপনে ব্যবহার করা :

while read -r k v; do
    echo "Key $k has value: $v"
done < <(printf '%s\n' 'key1 val1' 'key2 val2' 'key3 val3')

Key key1 has value: val1
Key key2 has value: val2
Key key3 has value: val3

উপরে প্রয়োজন bash। যদি bashব্যবহার না করা হয় তবে সাধারণ পাইপলাইনটি ব্যবহার করুন:

printf '%s\n' 'key1 val1' 'key2 val2' 'key3 val3' |
while read -r k v; do echo "Key $k has value: $v"; done

4
হ্যাঁ! অনুভা, তুমি মিষ্টি প্রতিভা!
স্কট

1
do echo $key $value
done < file_discriptor

উদাহরণ স্বরূপ:

$ while read key value; do echo $key $value ;done <<EOF
> c 3
> e 5
> EOF
c 3
e 5

$ echo -e 'c 3\ne 5' > file

$ while read key value; do echo $key $value ;done <file
c 3
e 5

$ echo -e 'c,3\ne,5' > file

$ while IFS=, read key value; do echo $key $value ;done <file
c 3
e 5


0

তবে কি যদি কোনও সহযোগী অ্যারে ধরে রাখতে পারে কে / ভি এর তুলনায় টিপলটি বেশি হয়? যদি এটি 3 বা 4 উপাদান হয়? এই ধারণাটি প্রসারিত করতে পারে:

###---------------------------------------------------
### VARIABLES
###---------------------------------------------------
myVars=(
    'ya1,ya2,ya3,ya4'
    'ye1,ye2,ye3,ye4'
    'yo1,yo2,yo3,yo4'
    )


###---------------------------------------------------
### MAIN PROGRAM
###---------------------------------------------------
### Echo all elements in the array
###---
printf '\n\n%s\n' "Print all elements in the array..."
for dataRow in "${myVars[@]}"; do
    while IFS=',' read -r var1 var2 var3 var4; do
        printf '%s\n' "$var1 - $var2 - $var3 - $var4"
    done <<< "$dataRow"
done

তারপরে আউটপুটটি এমন কিছু দেখাচ্ছে:

$ ./assoc-array-tinkering.sh 

Print all elements in the array...
ya1 - ya2 - ya3 - ya4
ye1 - ye2 - ye3 - ye4
yo1 - yo2 - yo3 - yo4

এবং উপাদানের সংখ্যা এখন সীমা ছাড়াই। ভোট খুঁজছেন না; শুধু জোরে চিন্তা করছি। REF1 , REF2


0

আমার টিউপল সংজ্ঞাগুলি আরও জটিল, সেই ক্ষেত্রে আমি এগুলিকে বংশগতভাবে রাখাই পছন্দ করি:

while IFS=", " read -ra arr; do
  echo "${arr[0]} and ${arr[1]}"
done <<EOM
c, 3
e, 5
EOM

এটি কোনও হেরডোকের লাইনের উপরে লুপিংকে কিছু পছন্দসই পৃথক চরিত্রের লাইনগুলি বিভক্ত করার সাথে একত্রিত করে

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