বাশে ভেরিয়েবল দ্বারা সংজ্ঞায়িত সংখ্যার বিস্তারে আমি কীভাবে পুনরাবৃত্তি করব?


1541

আমি যখন ব্যাশিয়াল দ্বারা পরিসীমা দেওয়া হয় তখন আমি কীভাবে ব্যাশের সংখ্যার ব্যাপ্তিতে পুনরাবৃত্তি করব?

আমি জানি আমি এটি করতে পারি (বাশ ডকুমেন্টেশনে "সিকোয়েন্স এক্সপ্রেশন" বলা হয় ):

 for i in {1..5}; do echo $i; done

যা দেয়:

1
2
3
4
5

তবুও, আমি কোনও পরিবর্তনশীলের সাথে পরিসীমাটির উভয় প্রান্তকে কীভাবে প্রতিস্থাপন করতে পারি? এটি কাজ করে না:

END=5
for i in {1..$END}; do echo $i; done

কোন মুদ্রণ:

{1..5}


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


9
বাশের কোন সংস্করণটি ঠিক ঠিক তেমন মনে নেই তবে এই কমান্ডটিও পিছনে শূন্যগুলিকে সমর্থন করে। যা কখনও কখনও সত্যিই সহায়ক হয়। কমান্ড for i in {01..10}; do echo $i; doneযেমন নম্বর দিতে হবে 01, 02, 03, ..., 10
টপার

1
আমার মতো যারা কেবল অ্যারের সূচকগুলির পরিসীমা নিয়ে পুনরাবৃত্তি করতে চান , বাশ উপায়টি হ'ল: myarray=('a' 'b' 'c'); for i in ${!myarray[@]}; do echo $i; done(বিস্মৃত চিহ্নটি লক্ষ্য করুন)। এটি মূল প্রশ্নের চেয়ে নির্দিষ্ট, তবে সাহায্য করতে পারে। দেখুন ব্যাশ প্যারামিটার প্রসারণও
PlasmaBinturong

1
ব্রেস সম্প্রসারণও এমন মত প্রকাশের জন্য ব্যবহৃত {jpg,png,gif}হয় যা এখানে সরাসরি সম্বোধন করা হয় না, যদিও উত্তরটি অভিন্ন হবে। পরিবর্তনশীল সহ ব্রেস সম্প্রসারণ দেখুন ? [সদৃশ] যা এটির সদৃশ হিসাবে চিহ্নিত আছে।
ট্রিপলি

উত্তর:


1741
for i in $(seq 1 $END); do echo $i; done

সম্পাদনা করুন: আমি seqঅন্যান্য পদ্ধতির তুলনায় পছন্দ করি কারণ আমি আসলে এটি মনে করতে পারি;)


36
seq একটি বাহ্যিক কমান্ড কার্যকর করা যা সাধারণত জিনিসগুলি ধীর করে দেয়। এটি গুরুত্বপূর্ণ নয় তবে আপনি যদি প্রচুর ডেটা হ্যান্ডেল করার জন্য কোনও স্ক্রিপ্ট লিখে থাকেন তবে তা গুরুত্বপূর্ণ হয়ে ওঠে।
paxdiablo

37
ওয়ান-লাইনারের জন্য ঠিক জরিমানা। প্যাক্সের সমাধানটিও খুব ভাল, তবে যদি পারফরম্যান্সটি সত্যিই উদ্বেগজনক হত তবে আমি শেল স্ক্রিপ্টটি ব্যবহার করতাম না।
এস্কারসিলে

17
সংখ্যাগুলি তৈরি করতে কেবল একবার সিক বলা হয়। এক্সিকিউটিভ () 'আইং এটি তাত্পর্যপূর্ণ হওয়া উচিত নয় যতক্ষণ না এই লুপটি অন্য টান লুপের ভিতরে থাকে।
জাভিয়ার

29
বাহ্যিক কমান্ডটি প্রকৃতপক্ষে সুদৃ external় নয়: আপনি যদি বাহ্যিক কমান্ডগুলি চালনার ওভারহেড সম্পর্কে উদ্বিগ্ন হন তবে আপনি শেল স্ক্রিপ্টগুলি মোটেও ব্যবহার করতে চান না, তবে সাধারণত ইউনিক্সে ওভারহেড কম থাকে। তবে এন্ডে বেশি হলে মেমোরি ব্যবহারের বিষয়টি রয়েছে।
মার্ক বাকের

18
লক্ষ্য করুন seq $ENDযথেষ্ট হবে, যেমন ডিফল্ট 1. FROM থেকে শুরু করার man seq: "প্রথম অথবা INCREMENT বাদ দেওয়া হয়, তাহলে এটি 1 ডিফল্ট"।
ফেডরকিই 'এসও ক্ষতিগ্রস্থ হওয়া বন্ধ করুন'

469

seqপদ্ধতি সহজ, কিন্তু ব্যাশ বিল্ট-ইন গাণিতিক মূল্যায়ন করেছে।

END=5
for ((i=1;i<=END;i++)); do
    echo $i
done
# ==> outputs 1 2 3 4 5 on separate lines

for ((expr1;expr2;expr3));কনস্ট্রাক্ট শুধু মত কাজ করে for (expr1;expr2;expr3)সি এবং অনুরূপ ভাষায়, এবং অন্যান্য মত ((expr))ক্ষেত্রে, ব্যাশ তাদের গাণিতিক হিসাবে একইরূপে।


67
এই ভাবে একটি বৃহত তালিকার মেমরির ওভারহেড এবং এর উপর নির্ভরতা এড়ানো যায় seq। এটা ব্যবহার করো!
বোবোগো

3
@MarinSagovac এই করে কাজ এবং কোন সিনট্যাক্স ত্রুটি আছে। আপনি কি নিশ্চিত যে আপনার শেল বাশ?
gniourf_gniourf

3
@ মেরিনসাগোভাক #!/bin/bashআপনার স্ক্রিপ্টের প্রথম লাইনটি নিশ্চিত করে নিন । wiki.ubuntu.com/…
মেলিবিয়াস

6
এ সম্পর্কে একটি খুব ছোট প্রশ্ন: কেন ((i = 1; i <= END; i ++)) এবং না ((i = 1; i <= $ সমাপ্তি; i ++)); কেন না $ শেষের আগে?
বেডসচ

5
@ বেডসচ: একই কারণে আমি $ i হিসাবে ব্যবহার করি না। পাটিগণিত মূল্যায়নের জন্য বাশ ম্যান পৃষ্ঠা বলছে: "একটি অভিব্যক্তির মধ্যে শেল ভেরিয়েবলগুলি পরামিতি প্রসারণ সিনট্যাক্স ব্যবহার না করে নাম দ্বারাও উল্লেখ করা যেতে পারে।"
ব্যবহারকারী3188140

192

আলোচনা

seqজিয়াআরোর পরামর্শ অনুসারে ব্যবহার করা ভাল। প্যাকস ডায়াবলো সাব-প্রসেসটি কল করা এড়াতে বাশ লুপের পরামর্শ দিয়েছিল, যদি $ END খুব বেশি বড় হয় তবে আরও মেমরি বান্ধব হওয়ার অতিরিক্ত সুবিধা রয়েছে। জ্যাথ্রুস লুপ প্রয়োগের ক্ষেত্রে একটি সাধারণ ত্রুটি চিহ্নিত করেছিল এবং এটি ইঙ্গিতও দেয় যেহেতু iএকটি পাঠ্য পরিবর্তনশীল, তাই সম্পর্কিত ধীরগতির সাথে নিয়মিত ধীরে ধীরে রূপান্তর করা হয়।

পূর্ণসংখ্যার গাণিতিক

এটি বাশ লুপের একটি উন্নত সংস্করণ:

typeset -i i END
let END=5 i=1
while ((i<=END)); do
    echo $i
    
    let i++
done

আমরা চাই যে একমাত্র জিনিস যদি হয় echo, তবে আমরা লিখতে পারে echo $((i++))

পূর্ববর্তী আমাকে কিছু শিখিয়েছে: বাশ for ((expr;expr;expr))নির্মাণের অনুমতি দেয় allows যেহেতু আমি বাশের জন্য পুরো ম্যান পৃষ্ঠাটি কখনও পড়িনি (যেমন আমি কর্ন শেল ( ksh) ম্যান পৃষ্ঠা দিয়ে করেছি এবং এটি অনেক দিন আগে ছিল) তাই আমি এটি মিস করেছি।

সুতরাং,

typeset -i i END # Let's be explicit
for ((i=1;i<=END;++i)); do echo $i; done

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

প্রাথমিক প্রশ্ন

এস্কের্কিলে উল্লেখ করেছেন যে; a .. b } বাশ স্বরলিপি কেবল আক্ষরিক সাথে কাজ করে; সত্য, বাশ ম্যানুয়াল অনুসারে। যে fork()কোনও একটি ছাড়াই একটি exec()( একক অভ্যন্তরীণ) দিয়ে এই বাধা অতিক্রম করতে পারে ( কলিংয়ের ক্ষেত্রে যেমনটি seqঅন্য চিত্র হিসাবে একটি কাঁটাচামচ করা আবশ্যক):

for i in $(eval echo "{1..$END}"); do

উভয় evalএবং echoবাশ বিল্টিনস, তবে fork()কমান্ড প্রতিস্থাপনের জন্য ( $(…)কনস্ট্রাক্ট) প্রয়োজনীয়।


1
সি স্টাইল লুপের একমাত্র ত্রুটি যে এটি "$" দিয়ে শুরু হওয়ার সাথে সাথে কমান্ড লাইন আর্গুমেন্টগুলি ব্যবহার করতে পারে না।
কারাতেডোগ

3
@ কারাতেডোগ: for ((i=$1;i<=$2;++i)); do echo $i; doneস্ক্রিপ্টে আমার জন্য বাশ v.4.1.9 এ ভাল কাজ করে, তাই কমান্ড লাইন আর্গুমেন্টে আমি কোনও সমস্যা দেখছি না। আপনি অন্য কিছু বোঝাতে চান?
tzot

দেখে মনে হয় যে, সি-এর মতো অন্তর্নিহিত: al সময় ((i = 1; i <= 100000; ++ i)) এর চেয়ে ইওল সলিউশনটি দ্রুতগতির চেয়ে দ্রুততর; কর:; বাস্তব 0m21.220s ব্যবহারকারীর 0m19.763s 0m1.203s ys সময় আমার জন্য in (সিচু ইকো "{1..100000}") এর জন্য sys; কর:; সম্পন্ন; বাস্তব 0m13.881s ব্যবহারকারী 0m13.536s sys 0m0.152s
মার্সিন জালুসকি

3
হ্যাঁ, তবে এভালটি খারাপ ... @ মার্সিনজালুস্কি time for i in $(seq 100000); do :; doneঅনেক দ্রুত!
এফ। হাউরি 2'13

কার্যকারিতা অবশ্যই প্ল্যাটফর্ম নির্দিষ্ট হতে হবে যেহেতু আমার মেশিনে ইভাল সংস্করণটি দ্রুত।
অ্যান্ড্রু প্রোক 23

102

আসল অভিব্যক্তিটি কেন কাজ করে না তা এখানে।

ম্যান বাশ থেকে :

অন্যান্য বর্ধনের আগে ব্রেস সম্প্রসারণ সম্পাদন করা হয়, এবং অন্যান্য বিস্তারের জন্য বিশেষ যে কোনও অক্ষরই ফলস্বরূপ সংরক্ষিত থাকে। এটি কঠোরভাবে পাঠ্য। বাশ কোনও প্রসারণের প্রসঙ্গে বা ধনুর্বন্ধনীগুলির মধ্যে পাঠ্যের প্রসঙ্গে কোন সিনট্যাক্টিক ব্যাখ্যা প্রয়োগ করে না।

সুতরাং, প্যারামিটারের প্রসারণের আগে, খাঁটি পাঠ্য ম্যাক্রো অপারেশন হিসাবে প্রথমে ব্রেস সম্প্রসারণ করা হয় is

শেলগুলি ম্যাক্রো প্রসেসর এবং আরও আনুষ্ঠানিক প্রোগ্রামিং ল্যাঙ্গুয়েজের মধ্যে অত্যন্ত অনুকূল সংকর। সাধারণ ব্যবহারের ক্ষেত্রে অনুকূলকরণের জন্য, ভাষাটিকে আরও জটিল করা হয় এবং কিছু সীমাবদ্ধতা গ্রহণ করা হয়।

সুপারিশ

আমি পজিক্স 1 বৈশিষ্ট্যগুলি স্টিকিংয়ের পরামর্শ দেব । এর অর্থ হল for i in <list>; do, যদি তালিকাটি ইতিমধ্যে জানা থাকে, অন্যথায়, ব্যবহার করুন whileবা seqযেমন রয়েছে:

#!/bin/sh

limit=4

i=1; while [ $i -le $limit ]; do
  echo $i
  i=$(($i + 1))
done
# Or -----------------------
for i in $(seq 1 $limit); do
  echo $i
done


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


13
আমার ক্ষমতা নেই, তবে আমি এটিকে বেশ কিছুটা উপরে নিয়ে যাব, সমস্ত বাশ নাভি-গ্যাজিংয়ের উপরে কিন্তু লুপ এবং পাটিগণিত মূল্যায়নের জন্য সি-স্টাইলের সাথে সাথেই।
mateor

2
একটি প্রচ্ছন্নতা হ'ল seqবড় পরিসরের তুলনায় তুলনামূলক সম্প্রসারণ খুব বেশি স্মৃতি সঞ্চয় করে না । যেমন, echo {1..1000000} | wcপ্রকাশ করে যে প্রতিধ্বনিটি 1 লাইন, এক মিলিয়ন শব্দ এবং 6,888,896 বাইট তৈরি করে। চেষ্টা করলে seq 1 1000000 | wcদশ মিলিয়ন লাইন, এক মিলিয়ন শব্দ এবং 6,888,896 বাইট পাওয়া যায় এবং timeকমান্ড দ্বারা পরিমাপ করা হিসাবে এটিও সাতগুণ বেশি দ্রুত faster
জর্জ

নোট: আমি POSIX উল্লেখ করেছিলেন while: পদ্ধতি পূর্বে আমার উত্তর stackoverflow.com/a/31365662/895245 কিন্তু আনন্দিত আপনি সম্মত হন :-)
সিরো Santilli冠状病毒审查六四事件法轮功

আমি এই উত্তরটি নীচে আমার কার্য সম্পাদনের তুলনায় উত্তরে অন্তর্ভুক্ত করেছি। stackoverflow.com/a/54770805/117471 (এই একটি নোট নিজেকে ট্র্যাক কোনটি আমি কিছু করার বাকি আছে রাখতে পারবেন।)
ব্রুনো Bronosky

@ পরিমাপক আমি ভেবেছিলাম লুপের জন্য সি-স্টাইল এবং পাটিগণিত মূল্যায়ন একই সমাধান। আমি কিছু অনুপস্থিত করছি?
অস্কার ঝাং

71

POSIX উপায়

আপনি যদি বহনযোগ্যতার বিষয়ে যত্নশীল হন তবে পসিক্স স্ট্যান্ডার্ড থেকে উদাহরণটি ব্যবহার করুন :

i=2
end=5
while [ $i -le $end ]; do
    echo $i
    i=$(($i+1))
done

আউটপুট:

2
3
4
5

যে জিনিসগুলি পসিক্স নয় :


এই উত্তরে সবেমাত্র 4 টি উর্ধ্বে ছিল যা অত্যন্ত অস্বাভাবিক। এটি যদি কোনও লিঙ্ক সমষ্টি ওয়েবসাইটে পোস্ট করা হয় তবে দয়া করে আমাকে একটি লিঙ্ক দিন, চিয়ার্স।
সিরো সান্তিলি 冠状 病毒 审查 六四 事件

উক্তিটি xসম্পূর্ণ এক্সপ্রেশনকে বোঝায় না। $((x + 1))ঠিক আছে।
চ্যানার

যখন পোর্টেবল না হয় এবং জিএনইউ থেকে পৃথক হয় seq(বিএসডি seqআপনাকে এর সাথে একটি সিকোয়েন্স টার্মিনেশন স্ট্রিং সেট করতে দেয় -t), ফ্রিবিএসডি এবং নেটবিএসডি এর seqযথাক্রমে 9.0 এবং 3.0 রয়েছে।
অ্যাড্রিয়ান গন্টার

@CiroSantilli @chepner $((x+1))এবং $((x + 1))পার্স ঠিক একই, যখন পার্সার tokenizes যেমন x+1এটা 3 টোকেন বিভক্ত করা হবে: x, +, এবং 1xএকটি বৈধ সংখ্যাসূচক টোকেন নয়, তবে এটি একটি বৈধ পরিবর্তনশীল নাম টোকেন, তবুও x+এটি নেই, তাই বিভক্ত। +একটি বৈধ পাটিগণিত অপারেটর টোকেন, তবুও +1এটি নেই, তাই টোকেনটি আবার সেখানে বিভক্ত হয়। এবং তাই এগিয়ে।
অ্যাড্রিয়ান গন্টার

আমি এই উত্তরটি নীচে আমার কার্য সম্পাদনের তুলনায় উত্তরে অন্তর্ভুক্ত করেছি। stackoverflow.com/a/54770805/117471 (এই একটি নোট নিজেকে ট্র্যাক কোনটি আমি কিছু করার বাকি আছে রাখতে পারবেন।)
ব্রুনো Bronosky

35

ইন্ডিয়ারেশনের আরেকটি স্তর:

for i in $(eval echo {1..$END}); do
    

2
+1: এছাড়াও, আমার জন্য al 1 ইন 'ইভাল ..' $ END '}; কর ... 'এই সমস্যাটি সমাধান করার প্রাকৃতিক উপায় বলে মনে হচ্ছে।
উইলিয়াম পার্সেল

28

তুমি ব্যবহার করতে পার

for i in $(seq $END); do echo $i; done

seq একটি বাহ্যিক কমান্ড কার্যকর করা যা সাধারণত জিনিসগুলি ধীর করে দেয়।
paxdiablo

9
এটি কেবল একবারে প্রতিটি পুনরাবৃত্তির জন্য বাহ্যিক কমান্ড কার্যকর করা জড়িত না। যদি একটি বাহ্যিক কমান্ড চালু করার সময়টি সমস্যা হয় তবে আপনি ভুল ভাষাটি ব্যবহার করছেন।
মার্ক বাকের

1
তাহলে কী কেবল বাসা বাঁধছে এই বিষয়টি? আমি ভাবছিলাম যে পারফরম্যান্সের পার্থক্য আছে কি না, নাকি কিছু অজানা প্রযুক্তিগত পার্শ্ব প্রতিক্রিয়া আছে?
স্কেয়াকি

: @Squeaky এটা একটা আলাদা প্রশ্ন whichtis উত্তর এখানে দেওয়া হচ্ছে stackoverflow.com/questions/4708549/...
tripleee

আমি এই উত্তরটি নীচে আমার কার্য সম্পাদনের তুলনায় উত্তরে অন্তর্ভুক্ত করেছি। stackoverflow.com/a/54770805/117471 (এই একটি নোট নিজেকে ট্র্যাক কোনটি আমি কিছু করার বাকি আছে রাখতে পারবেন।)
ব্রুনো Bronosky

21

আপনার যদি এটির প্রফিক্সের প্রয়োজন হয় তবে এটি আপনার পছন্দ হতে পারে

 for ((i=7;i<=12;i++)); do echo `printf "%2.0d\n" $i |sed "s/ /0/"`;done

ফলন হবে

07
08
09
10
11
12

4
এর printf "%02d\n" $iচেয়ে সহজ হবে না printf "%2.0d\n" $i |sed "s/ /0/"?
zb226

19

আপনি বিএসডি / ওএস এক্স এ থাকলে সিকের পরিবর্তে জট ব্যবহার করতে পারেন:

for i in $(jot $END); do echo $i; done

17

এটি এতে ভাল কাজ করে bash:

END=5
i=1 ; while [[ $i -le $END ]] ; do
    echo $i
    ((i = i + 1))
done

6
echo $((i++))এটি কাজ করে এবং এটি একটি লাইনে একত্রিত করে।
ব্রুনো ব্রোনোস্কি

1
এটিতে অযৌক্তিক বাশ এক্সটেনশন রয়েছে। একজন POSIX সংস্করণ: stackoverflow.com/a/31365662/895245
সিরো Santilli冠状病毒审查六四事件法轮功

1
@ সিরো, যেহেতু প্রশ্নটি বিশেষত ব্যাশকে বলেছে এবং এতে ব্যাশ ট্যাগ রয়েছে, আমি মনে করি আপনি সম্ভবত খুঁজে পাবেন যে বাশ 'এক্সটেনশনগুলি' ঠিক আছে এর চেয়ে বেশি :-)
প্যাক্সিডাব্লো

@ পাক্সাদিয়াবলো আমার অর্থ এই নয় যে এটি সঠিক নয়, তবে আমরা যখন পারি তখন পোর্টেবল হতে পারি না কেন ;-)
সিওরো সান্তিলি 法轮功 病毒 审查 六四 事件 法轮功

ইন bash, আমরা কেবল while [[ i++ -le "$END" ]]; doপরীক্ষায় (উত্তর) বর্ধনের জন্য করতে পারি
অ্যারন ম্যাকডেইড

14

আমি এখানে কয়েকটি ধারণাকে একত্রিত করেছি এবং কর্মক্ষমতা পরিমাপ করেছি।

টিএল; ডিআর টেকওয়েস:

  1. seqএবং {..}সত্যিই দ্রুত
  2. forএবং whileলুপগুলি ধীরে ধীরে
  3. $( ) ধীর
  4. for (( ; ; )) লুপগুলি ধীর হয়
  5. $(( )) এমনকি ধীর
  6. সম্পর্কে উদ্বেজক এন (অন্তত 1 মিলিয়ন পর্যন্ত।) ({..} SeQ বা) নিরীহ মেমরি টি সংখ্যার

এগুলি কোন সিদ্ধান্ত নয় । সিদ্ধান্তগুলি আঁকতে আপনাকে এগুলির প্রতিটিটির পিছনে সি কোডটি দেখতে হবে। কোড লুপিংয়ের জন্য আমরা এই প্রক্রিয়াটির প্রতিটি কীভাবে ব্যবহার করি তা সম্পর্কে এটি আরও বেশি। বেশিরভাগ একক ক্রিয়াকলাপগুলি একই গতিতে পর্যাপ্ত হয় যা বেশিরভাগ ক্ষেত্রে তা বিবেচ্য নয়। for (( i=1; i<=1000000; i++ ))আপনি যেমন দেখতে পারেন তেমন একটি প্রক্রিয়া অনেকগুলি অপারেশন। এটি লুপের চেয়ে আরও অনেক বেশি অপারেশন for i in $(seq 1 1000000)। এবং এটি আপনার কাছে স্পষ্ট নাও হতে পারে, এজন্য এই জাতীয় পরীক্ষা করা মূল্যবান।

গণদেবতা

# show that seq is fast
$ time (seq 1 1000000 | wc)
 1000000 1000000 6888894

real    0m0.227s
user    0m0.239s
sys     0m0.008s

# show that {..} is fast
$ time (echo {1..1000000} | wc)
       1 1000000 6888896

real    0m1.778s
user    0m1.735s
sys     0m0.072s

# Show that for loops (even with a : noop) are slow
$ time (for i in {1..1000000} ; do :; done | wc)
       0       0       0

real    0m3.642s
user    0m3.582s
sys 0m0.057s

# show that echo is slow
$ time (for i in {1..1000000} ; do echo $i; done | wc)
 1000000 1000000 6888896

real    0m7.480s
user    0m6.803s
sys     0m2.580s

$ time (for i in $(seq 1 1000000) ; do echo $i; done | wc)
 1000000 1000000 6888894

real    0m7.029s
user    0m6.335s
sys     0m2.666s

# show that C-style for loops are slower
$ time (for (( i=1; i<=1000000; i++ )) ; do echo $i; done | wc)
 1000000 1000000 6888896

real    0m12.391s
user    0m11.069s
sys     0m3.437s

# show that arithmetic expansion is even slower
$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $i; i=$(($i+1)); done | wc)
 1000000 1000000 6888896

real    0m19.696s
user    0m18.017s
sys     0m3.806s

$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $i; ((i=i+1)); done | wc)
 1000000 1000000 6888896

real    0m18.629s
user    0m16.843s
sys     0m3.936s

$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $((i++)); done | wc)
 1000000 1000000 6888896

real    0m17.012s
user    0m15.319s
sys     0m3.906s

# even a noop is slow
$ time (i=1; e=1000000; while [ $((i++)) -le $e ]; do :; done | wc)
       0       0       0

real    0m12.679s
user    0m11.658s
sys 0m1.004s

1
নিস! যদিও আপনার সারাংশের সাথে একমত হন না। আমার কাছে দেখতে $(seq)যেমন গতি হয় তেমনই {a..b}। এছাড়াও, প্রতিটি অপারেশন প্রায় একই সময় নেয়, তাই আমার জন্য লুপের প্রতিটি পুনরাবৃত্তিতে প্রায় 4μs যোগ করে। এখানে একটি অপারেশন শরীরে প্রতিধ্বনি , একটি পাটিগণিত তুলনা, একটি বৃদ্ধি, ইত্যাদি এই কোন অবাক বিস্ময়কর? লুপ প্যারাফেরানালিয়াটি এর কাজটি করতে কতক্ষণ সময় নেয় কে কে খেয়াল করে — রানটাইমটি লুপের বিষয়বস্তু দ্বারা প্রভাবিত হতে পারে।
বোবোগো

@ বোবোগো আপনি ঠিক বলেছেন, এটি সত্যই অপারেশন গণনা সম্পর্কে। আমি এই প্রতিফলিত করতে আমার উত্তর আপডেট। আমরা প্রত্যাশা করি তার চেয়ে বেশি কলগুলি আমরা আসলে করি operations আমি যে 50 টি টেস্ট চালিয়েছিলাম তার তালিকা থেকে আমি এটিকে সঙ্কুচিত করেছিলাম। আমি প্রত্যাশা করেছিলাম যে আমার গবেষণা এমনকি এই জনতার পক্ষে খুব সংবেদনশীল ছিল। সর্বদা হিসাবে, আমি আপনার কোডিংয়ের প্রয়াসকে অগ্রাধিকার দেওয়ার পরামর্শ দিচ্ছি: এটিকে আরও খাটো করুন; এটি পাঠযোগ্য; এটি দ্রুত করুন; এটি পোর্টেবল করুন। প্রায়শই # 1 কারণে # 3 হয়। আপনার প্রয়োজন অবধি # 4 এ আপনার সময় নষ্ট করবেন না।
ব্রুনো ব্রোনোস্কি

8

আমি জানি এই প্রশ্নটি সম্পর্কে bash, তবে - কেবলমাত্র রেকর্ডের জন্য - ksh93এটি স্মার্ট এবং এটি প্রত্যাশার মতো প্রয়োগ করে:

$ ksh -c 'i=5; for x in {1..$i}; do echo "$x"; done'
1
2
3
4
5
$ ksh -c 'echo $KSH_VERSION'
Version JM 93u+ 2012-02-29

$ bash -c 'i=5; for x in {1..$i}; do echo "$x"; done'
{1..5}

8

এটি অন্য উপায়:

end=5
for i in $(bash -c "echo {1..${end}}"); do echo $i; done

1
এটিতে একটি অন্য শেল তৈরির ওভারহেড রয়েছে।
কোডফোরস্টার

1
প্রকৃতপক্ষে, এটি অতিরিক্ত ভয়ঙ্কর কারণ এটি 2 টি শাঁস তৈরি করে যখন 1 পর্যাপ্ত হবে।
ব্রুনো ব্রোনোস্কি

8

আপনি যদি ব্রেস-এক্সপ্রেশন সিনট্যাক্সের যথাসম্ভব কাছাকাছি থাকতে চান, তবে rangeবাশ-কৌশলগুলি থেকে ফাংশনটি ব্যবহার করে দেখুনrange.bash

উদাহরণস্বরূপ, নীচের সমস্তগুলি ঠিক একই জিনিসটি করবে echo {1..10}:

source range.bash
one=1
ten=10

range {$one..$ten}
range $one $ten
range {1..$ten}
range {1..10}

এটি দেশী বাশ বাক্য গঠনটিকে যতটা সম্ভব "গটচস" দিয়ে সমর্থন করার চেষ্টা করে: কেবলমাত্র ভেরিয়েবল সমর্থিত হয় না, তবে স্ট্রিং (যেমন for i in {1..a}; do echo $i; done) হিসাবে সরবরাহ করা অবৈধ পরিসরের প্রায়শ-অনাকাঙ্ক্ষিত আচরণও প্রতিরোধ করা হয়।

অন্যান্য উত্তর বেশিরভাগ ক্ষেত্রে কাজ করবে, তবে সেগুলির নিম্নলিখিতগুলির মধ্যে কমপক্ষে একটির কমতি রয়েছে:

  • তাদের মধ্যে অনেকগুলি সাব-শেল ব্যবহার করে যা কার্য সম্পাদনকে ক্ষতি করতে পারে এবং কিছু সিস্টেমে এটি সম্ভব নাও হতে পারে
  • তাদের মধ্যে অনেকে বহিরাগত প্রোগ্রামগুলির উপর নির্ভর করে। এমনকি seqএটি একটি বাইনারি যা ব্যবহারের জন্য ইনস্টল করা আবশ্যক, অবশ্যই ব্যাশ দ্বারা লোড করা উচিত এবং অবশ্যই এই প্রোগ্রামটিতে কাজ করার জন্য আপনার যে প্রোগ্রামটি প্রত্যাশা করা উচিত তা অবশ্যই এতে থাকা উচিত। সর্বব্যাপী বা না, কেবলমাত্র বাশ ভাষার চেয়ে বেশি নির্ভর করা।
  • @ ইফেমিয়েন্টের মতো কেবল নেটিভ বাশ কার্যকারিতা ব্যবহার করে এমন সমাধানগুলি বর্ণানুক্রমিক রেঞ্জগুলিতে কাজ করবে না, যেমন {a..z}; বন্ধনী সম্প্রসারণ হবে। প্রশ্নটি সংখ্যাগুলির ব্যাপ্তি সম্পর্কে ছিল , তবে এটি একটি বিচক্ষণ।
  • তাদের বেশিরভাগ {1..10}ব্রেস-প্রসারিত পরিসীমা সিনট্যাক্সের সাথে চাক্ষুষভাবে অনুরূপ নয় , সুতরাং যে দুটি প্রোগ্রাম ব্যবহার করে সেগুলি পড়তে খুব সামান্য কঠিন হতে পারে।
  • @ ববোগোগোর উত্তরটি কিছু পরিচিত সিনট্যাক্স ব্যবহার করে, তবে যদি $ENDভেরিয়েবলটি ব্যাপ্তিটির অন্য পাশের জন্য বৈধ পরিসর "বুকএন্ড" না হয় তবে অপ্রত্যাশিত কিছু করে does যদি END=a, উদাহরণস্বরূপ, একটি ত্রুটি সৃষ্টি হবে না এবং ধারণকৃত মান {1..a}প্রতিধ্বনিত করা হবে না। এটি বাশের ডিফল্ট আচরণও - এটি প্রায়শই অপ্রত্যাশিত।

দাবি অস্বীকার: আমি সংযুক্ত কোডের লেখক।


7

প্রতিস্থাপন {}সঙ্গে (( )):

tmpstart=0;
tmpend=4;

for (( i=$tmpstart; i<=$tmpend; i++ )) ; do 
echo $i ;
done

উৎপাদনের:

0
1
2
3
4

আমি এই উত্তরটি নীচে আমার কার্য সম্পাদনের তুলনায় উত্তরে অন্তর্ভুক্ত করেছি। stackoverflow.com/a/54770805/117471 (আমি কোনটি করতে গিয়েছি তা সম্পর্কে নজর রাখার জন্য এটি আমার কাছে একটি নোট।)
ব্রুনো ব্রোনোস্কি

6

এগুলি সবই দুর্দান্ত তবে সিকটি অনুমিতভাবে অবহিত এবং বেশিরভাগটি কেবলমাত্র সীমাবদ্ধতার সাথে কাজ করে।

আপনি যদি ডাবল উদ্ধৃতিতে লুপের জন্য আবদ্ধ করেন, আপনি যখন স্ট্রিং প্রতিধ্বনি করবেন তখন শুরু এবং শেষের ভেরিয়েবলগুলি ডিফারেন্স করা হবে এবং আপনি সম্পাদনার জন্য স্ট্রিংটি সরাসরি BASH এ শিপ করতে পারবেন। $iএর সাথে পালানো দরকার তাই সাব-শেল পাঠানোর আগে এটি মূল্যায়ন করা হয় না।

RANGE_START=a
RANGE_END=z
echo -e "for i in {$RANGE_START..$RANGE_END}; do echo \\${i}; done" | bash

এই আউটপুটটি একটি চলককেও বরাদ্দ করা যেতে পারে:

VAR=`echo -e "for i in {$RANGE_START..$RANGE_END}; do echo \\${i}; done" | bash`

কেবলমাত্র "ওভারহেড" এটি উত্পন্ন করা উচিত বাশের দ্বিতীয় উদাহরণ হওয়া উচিত তাই এটি নিবিড় ক্রিয়াকলাপগুলির জন্য উপযুক্ত।


5

যদি আপনি শেল কমান্ডগুলি করেন এবং আপনার (যেমন আমি) পাইপলাইনের জন্য একটি প্রতিমা পেয়ে থাকেন তবে এটি ভাল is

seq 1 $END | xargs -I {} echo {}


3

এটি করার অনেকগুলি উপায় রয়েছে, তবে আমি যা পছন্দ করি তা নীচে দেওয়া আছে

ব্যবহার seq

থেকে সংক্ষিপ্তসার man seq

$ seq [-w] [-f format] [-s string] [-t string] [first [incr]] last

বাক্য গঠন

সম্পূর্ণ কমান্ড
seq first incr last

  • প্রথমে ক্রমটিতে নম্বর শুরু হচ্ছে [ডিফল্টরূপে alচ্ছিক: 1]
  • incr হ'ল বৃদ্ধি [ডিফল্টরূপে optionচ্ছিক: 1]
  • সিকোয়েন্সে সর্বশেষতম সংখ্যাটি

উদাহরণ:

$ seq 1 2 10
1 3 5 7 9

কেবল প্রথম এবং শেষের সাথে:

$ seq 1 5
1 2 3 4 5

শুধুমাত্র শেষের সাথে:

$ seq 5
1 2 3 4 5

ব্যবহার {first..last..incr}

এখানে প্রথম এবং শেষ বাধ্যতামূলক এবং incr optionচ্ছিক

ঠিক প্রথম এবং শেষ ব্যবহার

$ echo {1..5}
1 2 3 4 5

Incr ব্যবহার করে

$ echo {1..10..2}
1 3 5 7 9

আপনি নীচের মত অক্ষরের জন্য এমনকি এটি ব্যবহার করতে পারেন

$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z

3

আপনি যদি ' seq' বা ' eval' অথবা jotবা পাটিগণিত সম্প্রসারণ বিন্যাস যেমন ব্যবহার করতে না চান তবে । for ((i=1;i<=END;i++)), বা অন্যান্য লুপগুলি যেমন। while, এবং আপনি ' printf' এবং ' echo' শুধুমাত্র খুশি হতে চান না , তবে এই সাধারণ কাজটি আপনার বাজেটের সাথে খাপ খায়:

a=1; b=5; d='for i in {'$a'..'$b'}; do echo -n "$i"; done;' echo "$d" | bash

পিএস: আমার বাশের কোনও seqনির্দেশ নেই '।

ম্যাক ওএসএক্স 10.6.8, বাশ 3.2.48 এ পরীক্ষিত


0

এটি বাশ এবং কর্নে কাজ করে, উচ্চ থেকে কম সংখ্যায়ও যেতে পারে। সম্ভবত দ্রুত বা prettiest না কিন্তু যথেষ্ট ভাল কাজ করে। নেতিবাচকগুলিও পরিচালনা করে।

function num_range {
   # Return a range of whole numbers from beginning value to ending value.
   # >>> num_range start end
   # start: Whole number to start with.
   # end: Whole number to end with.
   typeset s e v
   s=${1}
   e=${2}
   if (( ${e} >= ${s} )); then
      v=${s}
      while (( ${v} <= ${e} )); do
         echo ${v}
         ((v=v+1))
      done
   elif (( ${e} < ${s} )); then
      v=${s}
      while (( ${v} >= ${e} )); do
         echo ${v}
         ((v=v-1))
      done
   fi
}

function test_num_range {
   num_range 1 3 | egrep "1|2|3" | assert_lc 3
   num_range 1 3 | head -1 | assert_eq 1
   num_range -1 1 | head -1 | assert_eq "-1"
   num_range 3 1 | egrep "1|2|3" | assert_lc 3
   num_range 3 1 | head -1 | assert_eq 3
   num_range 1 -1 | tail -1 | assert_eq "-1"
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.