Bash හි විචල්යයන් මගින් අර්ථ දක්වා ඇති සංඛ්යා පරාසයක් හරහා මම නැවත කියන්නේ කෙසේද?


1589

විචල්‍යය මඟින් පරාසය ලබා දෙන විට, මම බාෂ් හි සංඛ්‍යා පරාසයක් හරහා නැවත ක්‍රියා කරන්නේ කෙසේද?

මට මෙය කළ හැකි බව මම දනිමි (බෑෂ් ප්‍රලේඛනයේ "අනුක්‍රමික ප්‍රකාශනය" ලෙස හැඳින්වේ ):

 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}


27
ආයුබෝවන්, මා මෙහි කියවා ඇති තොරතුරු සහ ඉඟි සියල්ලම ඇත්තෙන්ම ප්‍රයෝජනවත් වේ. මම හිතන්නේ seq භාවිතය වළක්වා ගැනීම වඩාත් සුදුසුයි. හේතුව, සමහර ස්ක්‍රිප්ට් අතේ ගෙන යා හැකි අතර සමහර විධාන නොතිබිය හැකි විවිධාකාර යුනික්ස් පද්ධති මත ධාවනය විය යුතුය. නිදසුනක් ලෙස, FreeBSD පද්ධතිවල පෙරනිමියෙන් seq නොපවතී.


10
Bash හි කුමන අනුවාදයේ සිටදැයි මට මතක නැත, නමුත් මෙම විධානය මඟින් ශුන්‍ය පසුපස ලුහුබැඳීමට සහාය වේ. සමහර විට එය ඇත්තෙන්ම ප්‍රයෝජනවත් වේ. විධානය for i in {01..10}; do echo $i; doneමඟින් අංක ලබා දෙනු 01, 02, 03, ..., 10ඇත.
topr

1
අරාවෙහි දර්ශක පරාසය ඉක්මවා යෑමට අවශ්‍ය මා වැනි අයට , කඩිනම් ක්‍රමය වනුයේ: myarray=('a' 'b' 'c'); for i in ${!myarray[@]}; do echo $i; done(විශ්මයජනක සලකුණ සටහන් කරන්න). එය මුල් ප්‍රශ්නයට වඩා විශේෂිත නමුත් උදව් කළ හැකිය.
Bash

1
{jpg,png,gif}මෙහි සෘජුවම ආමන්ත්‍රණය නොකරන ප්‍රකාශන සඳහා වරහන් ප්‍රසාරණය ද යොදා ගනී , නමුත් පිළිතුර සමාන වනු ඇත. විචල්යය සමඟ වරහන් පුළුල් කිරීම බලන්න ? [අනුපිටපත] මෙය අනුපිටපතක් ලෙස සලකුණු කර ඇත.
ත්‍රිත්ව

Answers:


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

සංස්කරණය කරන්න: මම seqඅනෙක් ක්‍රමවලට වඩා කැමතියි එය මට මතක තබා ගත හැකි නිසා;)


38
seq යනු සාමාන්‍යයෙන් දේවල් මන්දගාමී වන බාහිර විධානයක් ක්‍රියාත්මක කිරීමයි. මෙය වැදගත් නොවිය හැකි නමුත් ඔබ බොහෝ දත්ත හැසිරවීමට පිටපතක් ලියන්නේ නම් එය වැදගත් වේ.
paxdiablo

38
එක් ලයිනර් සඳහා හොඳයි. පැක්ස්ගේ විසඳුම ද හොඳයි, නමුත් කාර්ය සාධනය සැබවින්ම සැලකිලිමත් වූයේ නම් මම ෂෙල් ස්ක්‍රිප්ට් භාවිතා නොකරමි.
eschercycle

17
සංඛ්‍යා උත්පාදනය කිරීම සඳහා එක් වරක් පමණක් seq ලෙස හැඳින්වේ. exec () 'මෙම ලූපය වෙනත් තද පුඩුවක් තුළ නොමැති නම් එය සැලකිය යුතු නොවේ.
ජේවියර්

29
බාහිර විධානය සැබවින්ම අදාළ නොවේ: බාහිර විධානයන් ක්‍රියාත්මක කිරීම ගැන ඔබ කනස්සල්ලට පත්වුවහොත් ඔබට කිසිසේත් ෂෙල් ස්ක්‍රිප්ට් භාවිතා කිරීමට අවශ්‍ය නැත, නමුත් සාමාන්‍යයෙන් යුනික්ස් මත උඩිස් මට්ටම අඩුය. කෙසේ වෙතත්, END ඉහළ මට්ටමක පවතී නම් මතක භාවිතය පිළිබඳ ගැටළුව පවතී.
මාර්ක් බේකර්

19
seq $ENDපෙරනිමිය 1 සිට ආරම්භ වන බැවින් එය ප්‍රමාණවත් බව සලකන්න. සිට man seq: "පළමු හෝ INCREMENT මඟ හැරී ඇත්නම්, එය පෙරනිමිය 1 දක්වා".
fedorqui 'SO නවත්වන්න'

485

මෙම 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))අවස්ථා වලදී මෙන් බාෂ් ඒවා ගණිතමය ලෙස සලකයි.


69
මේ ආකාරයෙන් විශාල ලැයිස්තුවක මතකය ඉහළින් තබා ගැනීම සහ යැපීම වළක්වයි seq. එය භාවිතා කරන්න!
බොබ්බෝගෝ

3
ArMarinSagovac මෙය ක්‍රියාත්මක වන අතර සින්ටැක්ස් දෝෂ නොමැත. ඔබේ ෂෙල් එක බාෂ් බව ඔබට විශ්වාසද?
gniourf_gniourf

3
ArMarinSagovac #!/bin/bashඔබේ පිටපතෙහි පළමු පේළිය සෑදීමට වග බලා ගන්න . wiki.ubuntu.com/…
මෙලෙබියස්

7
ඒ පිළිබඳ ඉතා කෙටි ප්‍රශ්නයක් පමණි: ඇයි ((i = 1; i <= END; i ++)) සහ NOT ((i = 1; i <= $ END; i ++)); END ට පෙර $ නැත්තේ ඇයි?
බේඩ්ස්

5
A බේඩ්ස්: එකම හේතුව නිසා මා $ i ලෙස භාවිතා නොකෙරේ. අංක ගණිතමය ඇගයීම සඳහා bash man පිටුවෙහි මෙසේ සඳහන් වේ: "ප්‍රකාශනයක් තුළ, පරාමිති විස්තාරණ සින්ටැක්ස් භාවිතා නොකර ෂෙල් විචල්‍යයන් නමෙන් ද සඳහන් කළ හැකිය."
user3188140

195

සාකච්ඡා

seqජියාරෝ යෝජනා කළ පරිදි භාවිතා කිරීම හොඳයි. පැක්ස් ඩයබ්ලෝ විසින් උපසිරැසියක් ඇමතීමෙන් වළක්වා ගැනීම සඳහා බෑෂ් ලූපයක් යෝජනා කළ අතර memory END ඉතා විශාල නම් මතක හිතකාමී වීමට අමතර වාසියක් ඇත. සැත්රස් ලූප ක්‍රියාත්මක කිරීමේදී සාමාන්‍ය දෝෂයක් දුටු අතර එතැන් සිට එය ඉඟි කළේයi , පෙළ විචල්‍යයක් වන බැවින්, සංඛ්‍යාංක වෙත අඛණ්ඩ පරිවර්තනයන් සම්බන්ධ වන්නේ මන්දගාමී වීමෙනි.

නිඛිල අංක ගණිතය

මෙය Bash loop හි වැඩිදියුණු කළ අනුවාදයකි:

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

අපට අවශ්‍ය එකම දෙය නම් echo, අපට ලිවිය හැකිය echo $((i++)).

ephemient මට යමක් ඉගැන්නුවා: Bash for ((expr;expr;expr))ඉදිකිරීම් සඳහා ඉඩ දෙයි . මම කවදාවත් බාෂ් සඳහා සම්පූර්ණ මෑන් පිටුව කියවා නැති නිසා (මම කෝර්න් ෂෙල් එකෙන් කළාක් මෙන්)ksh ) මෑන් පිටුව සමඟ කර ඇති පරිදි, එය බොහෝ කලකට පෙර සිදු වූවක් මෙන්), මට එය මග හැරුණි.

නිසා,

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

වඩාත්ම මතක-කාර්යක්ෂම ක්‍රමය ලෙස පෙනේ (පරිභෝජනය සඳහා මතකය වෙන් කිරීම අවශ්‍ය නොවේ seq නිමැවුම් , එය END ඉතා විශාල නම් ගැටළුවක් විය හැකිය), බොහෝ විට “වේගවත්ම” නොවේ.

ආරම්භක ප්‍රශ්නය

eshercycle සඳහන් කළේ { a .. b } බෑෂ් අංකනය ක්‍රියාත්මක වන්නේ වචනාර්ථයෙන් පමණක් බවයි; සත්‍ය, බාෂ් අත්පොතට අනුව. කෙනෙකුට මෙම බාධකය තනි (අභ්‍යන්තර) fork()රහිතව ජය ගත හැකිය (ඇමතුම exec()මෙන්ම seq, වෙනත් රූපයක් සඳහා දෙබලක + ක්‍රියාත්මක කිරීමක් අවශ්‍ය වේ):

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

දෙකම evalසහ echoBash buildins වේ, නමුත් fork()විධාන ආදේශනය සඳහා ( $(…)ඉදිකිරීම්) අවශ්‍ය වේ.


1
සී ස්ටයිල් ලූපයට ඇති එකම අඩුපාඩුව වන්නේ විධාන රේඛා තර්ක භාවිතා කළ නොහැකි වීමයි.
karatedog

3
ated kratedog: for ((i=$1;i<=$2;++i)); do echo $i; doneස්ක්‍රිප්ටයක බාෂ් v.4.1.9 හි මට හොඳින් ක්‍රියා කරයි, එබැවින් විධාන රේඛා තර්ක සමඟ ගැටළුවක් මට නොපෙනේ. ඔබ වෙනත් දෙයක් අදහස් කරනවාද?
tzot

සී-වැනි සඳහා සාදන ලද ඒවාට වඩා එවාල් විසඳුම වේගවත් බව පෙනේ: for සඳහා කාලය ((i = 1; i <= 100000; ++ i)); කරන්න :; සැබෑ 0m21.220s පරිශීලක 0m19.763s sys 0m1.203s i i in in in කාලය (eval echo "{1..100000}"); කරන්න :; සිදු කරන ලදී; තාත්වික 0m13.881s පරිශීලක 0m13.536s sys 0m0.152s
Marcin Zaluski

3
ඔව්, නමුත් එවාල් නපුරුයි ... ar මාකින්සාලුස්කි time for i in $(seq 100000); do :; doneඉතා ඉක්මන් ය!
එෆ්. හවුරි

මගේ පරිගණකයේ එවාල් අනුවාදය ඉක්මන් වන බැවින් කාර්ය සාධනය වේදිකා විශේෂිත විය යුතුය.
ඇන්ඩ rew ප්‍රොක්

105

මෙන්න මුල් ප්‍රකාශනය ක්‍රියාත්මක නොවීමට හේතුව.

මෑන් බැෂ් වෙතින් :

වෙනත් ඕනෑම ප්‍රසාරණයකට පෙර වරහන් ප්‍රසාරණය සිදු කරනු ලබන අතර, වෙනත් පුළුල් කිරීම් වලට විශේෂිත වූ ඕනෑම අක්‍ෂරයක් ප්‍රති .ලය තුළ ආරක්ෂා වේ. එය තදින් පා ual මය. පුළුල් කිරීමේ සන්දර්භය හෝ වරහන් අතර ඇති පෙළට බාෂ් කිසිදු සින්ටැක්ටික් අර්ථකථනයක් අදාළ නොකරයි.

එබැවින්, වරහන් ප්‍රසාරණය යනු පරාමිති ප්‍රසාරණයට පෙර තනිකරම පා ma මය සාර්ව මෙහෙයුමක් ලෙස කළ හැකි දෙයකි .

ෂෙල් වෙඩි යනු සාර්ව සකසනයන් සහ වඩාත් විධිමත් ක්‍රමලේඛන භාෂා අතර ඉහළ ප්‍රශස්ත දෙමුහුන් ය. සාමාන්‍ය භාවිත අවස්ථා ප්‍රශස්ත කිරීම සඳහා, භාෂාව වඩාත් සංකීර්ණ කර ඇති අතර සමහර සීමාවන් පිළිගනු ලැබේ.

නිර්දේශය

පොසික්ස් 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


1. Bash යනු විශිෂ්ට කවචයක් වන අතර මම එය අන්තර්ක්‍රියාකාරීව භාවිතා කරමි, නමුත් මම මගේ ස්ක්‍රිප්ට් වලට bash-isms දමන්නේ නැත. ස්ක්‍රිප්ට් වලට වේගවත් කවචයක්, වඩා ආරක්ෂිත එකක්, වඩා කාවැද්දූ විලාසිතාවක් අවශ්‍ය විය හැකිය. ඔවුන්ට / bin / sh ලෙස ස්ථාපනය කර ඇති ඕනෑම දෙයක් ක්‍රියාත්මක කිරීමට අවශ්‍ය විය හැකිය, එවිට සුපුරුදු ප්‍රමිති ගැති තර්ක තිබේ. මතක තබා ගන්න shellshock, හෙවත් bashdoor?


14
මට බලයක් නැත, නමුත් මම මෙය තරමක් ඉහළට ඔසවා තබමි, සියල්ලටම වඩා නහය දෙස බැලූ නමුත් ලූප සහ ගණිතමය ඇගයීම සඳහා සී විලාසිතාවෙන් පසු.
සහකරු

2
ඇඟවුම් කරන්නේ seqවිශාල පරාසයන්ට සාපේක්ෂව වරහන් ප්‍රසාරණය වැඩි මතකයක් ඉතිරි නොකරන බවයි . උදා: echo {1..1000000} | wcදෝංකාරය මඟින් පේළියක්, වචන මිලියනයක් සහ බයිට් 6,888,896 ක් නිපදවන බව අනාවරණය වේ. උත්සාහ කිරීමෙන් seq 1 1000000 | wcපේළි මිලියනයක්, වචන මිලියනයක් සහ බයිට් 6,888,896 ක් ලැබෙන අතර එය timeවිධානය මගින් මනිනු ලබන පරිදි හත් ගුණයකින් වේගවත් වේ.
ජෝර්ජ්

සටහන: මම whileමීට පෙර මගේ පිළිතුරෙහි POSIX ක්‍රමය සඳහන් කර ඇත්තෙමි : stackoverflow.com/a/31365662/895245 නමුත් ඔබ එකඟ වීම සතුටක් :-)
සිරෝ සැන්ටිලි 郝海东 冠状 病 六四 法轮功 法轮功

මම මෙම පිළිතුර මගේ කාර්ය සාධන සංසන්දනාත්මක පිළිතුරට පහත ඇතුළත් කර ඇත්තෙමි. stackoverflow.com/a/54770805/117471 (මෙය කිරීමට මට ඉතිරිව ඇති ඒවා පිළිබඳව සොයා බැලීමට මෙය සටහනකි .)
බ un නෝ බ්‍රොනොස්කි

@mateor මම සිතුවේ ලූප සහ ගණිතමය ඇගයීම සඳහා සී-ස්ටයිල් එකම විසඳුම බවයි. මට යමක් මග හැරී තිබේද?
ඔස්කාර් ෂැං

75

POSIX මාර්ගය

ඔබ අතේ ගෙන යා හැකි බව ගැන සැලකිලිමත් නම් , POSIX ප්‍රමිතියෙන් උදාහරණය භාවිතා කරන්න :

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

ප්‍රතිදානය:

2
3
4
5

පොසික්ස් නොවන දේවල් :


මෙම පිළිතුරට උඩු යටිකුරු 4 ක් තිබීම අසාමාන්‍යය. මෙය කිසියම් සම්බන්ධක වෙබ් අඩවියක පළ කර ඇත්නම්, කරුණාකර මට සබැඳියක් දෙන්න, චියර්ස්.
සිරෝ සැන්ටිලි 郝海东 冠状 病 六四 事件 法轮功

උපුටා දැක්වීමෙන් අදහස් කරන්නේ xසමස්ත ප්‍රකාශනයම නොවේ. $((x + 1))හොඳයි.
චෙප්නර්

අතේ ගෙන යා නොහැකි අතර GNU ට වඩා වෙනස් seq(BSD seqමඟින් අනුක්‍රමික අවසන් කිරීමේ නූලක් සැකසීමට ඔබට ඉඩ සලසයි -t), FreeBSD සහ NetBSD seqපිළිවෙලින් 9.0 සහ 3.0 සිට ඇත.
ඒඩ්‍රියන් ගුන්ටර්

@CiroSantilli @chepner $((x+1)) හා $((x + 1))විග්රහකය tokenizes විට, හරියටම එම විග්රහ කළ x+1එය ඇඟවුම් කරන 3 කට බෙදී ඇත: x, +, සහ 1. xවලංගු සංඛ්‍යාත්මක ටෝකනයක් නොවේ, නමුත් එය වලංගු විචල්‍ය නාම ටෝකනයකි, නමුත් x+එසේ නොවේ, එබැවින් භේදය. +වලංගු අංක ගණිත ක්‍රියාකරු ටෝකනයකි, නමුත් +1එසේ නොවේ, එබැවින් ටෝකනය නැවත එහි බෙදී යයි. සහ එසේ ය.
ඒඩ්‍රියන් ගුන්ටර්

මම මෙම පිළිතුර මගේ කාර්ය සාධන සංසන්දනාත්මක පිළිතුරට පහත ඇතුළත් කර ඇත්තෙමි. stackoverflow.com/a/54770805/117471 (මෙය කිරීමට මට ඉතිරිව ඇති ඒවා පිළිබඳව සොයා බැලීමට මෙය සටහනකි .)
බ un නෝ බ්‍රොනොස්කි

35

අවිනිශ්චිතතාවයේ තවත් ස්ථරයක්:

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

2
+1: එසේම, ev 1 සඳහා i සඳහා .. '$ END'}; do ... 'eval මෙම ගැටලුව විසඳීමේ ස්වාභාවික ක්‍රමය ලෙස පෙනේ.
විලියම් පර්සෙල්

28

ඔයාට පාවිච්චි කරන්න පුළුවන්

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

seq යනු සාමාන්‍යයෙන් දේවල් මන්දගාමී වන බාහිර විධානයක් ක්‍රියාත්මක කිරීමයි.
paxdiablo

9
එක් එක් පුනරාවර්තනය සඳහා එක් වරක් පමණක් බාහිර විධානයක් ක්‍රියාත්මක කිරීම එයට සම්බන්ධ නොවේ. එක් බාහිර විධානයක් දියත් කිරීමට කාලය ගැටළුවක් නම්, ඔබ භාවිතා කරන්නේ වැරදි භාෂාවකි.
මාර්ක් බේකර්

1
මෙය වැදගත් වන එකම අවස්ථාව කැදැල්ලද? කාර්ය සාධන වෙනසක් හෝ නොදන්නා තාක්ෂණික අතුරු ආබාධයක් තිබේදැයි මම කල්පනා කළෙමි.
Sqeaky

Qu ස්කීකි එය වෙනම ප්‍රශ්නයක් වන අතර එයට පිළිතුරු සපයන ලද්දේ: stackoverflow.com/questions/4708549/…
ත්‍රිත්ව

මම මෙම පිළිතුර මගේ කාර්ය සාධන සංසන්දනාත්මක පිළිතුරට පහත ඇතුළත් කර ඇත්තෙමි. stackoverflow.com/a/54770805/117471 (මෙය කිරීමට මට ඉතිරිව ඇති ඒවා පිළිබඳව සොයා බැලීමට මෙය සටහනකි .)
බ un නෝ බ්‍රොනොස්කි

22

ඔබට මෙය අවශ්‍ය වීමට වඩා උපසර්ගය අවශ්‍ය නම්

 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

20

ඔබ BSD / OS X හි සිටී නම් ඔබට seq වෙනුවට jot භාවිතා කළ හැකිය:

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

18

මෙය හොඳින් ක්‍රියාත්මක වේ bash:

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

6
echo $((i++))ක්‍රියා කර එය එක් පේළියකට ඒකාබද්ධ කරයි.
බ un නෝ බ්‍රොනොස්කි

1
මෙය අනවශ්‍ය බෑෂ් දිගු ඇත. POSIX අනුවාදය: stackoverflow.com/a/31365662/895245
සිරෝ සැන්ටිලි 郝海东 冠状 病 六四 法轮功 法轮功

1
@ සයිරෝ, ප්‍රශ්නයේ විශේෂයෙන් බැෂ් සඳහන් වන අතර, බෑෂ් ටැග් එකක් ඇති බැවින්, මම සිතන්නේ ඔබ බොහෝ විට 'දිගුවන්' වඩා හොඳ බව සොයා ගනීවි :-)
paxdiablo

@paxdiablo මම කියන්නේ එය නිවැරදි නොවන බවයි, නමුත් අපට හැකි විට අතේ ගෙන යා නොහැක්කේ ඇයි ;-)
සීරෝ සැන්ටිලි 郝海东 冠状 病 六四 法轮功 法轮功

දී bash, while [[ i++ -le "$END" ]]; doපරීක්ෂණයේ (පශ්චාත්) වර්ධක කිරීම සඳහා අපට සරලවම කළ හැකිය
ආරොන් මැක්ඩේඩ්

15

මම මෙහි අදහස් කිහිපයක් ඒකාබද්ධ කර කාර්ය සාධනය මැන බැලුවෙමි.

ටීඑල්; ඩීආර් රැගෙන යාම:

  1. seq සහ {..} ඇත්තටම වේගවත්
  2. forසහ whileලූප මන්දගාමී වේ
  3. $( ) මන්දගාමී වේ
  4. for (( ; ; )) ලූප මන්දගාමී වේ
  5. $(( )) ඊටත් වඩා මන්දගාමී වේ
  6. ගැන කනගාටු එන් (මහලේකම් පා හෝ {..}) මතකයේ අංක (මිලියන 1 දක්වා අවම වශයෙන් දක්වා දී.) ඒක වෙනස්

මේවා නිගමන නොවේ . නිගමන උකහා ගැනීම සඳහා ඔබට මේ සෑම එකක් පිටුපස ඇති සී කේතය දෙස බැලිය යුතුය. කේතය ඉක්මවා යාම සඳහා මෙම එක් එක් යාන්ත්‍රණය භාවිතා කිරීමට අපි නැඹුරු වන්නේ කෙසේද යන්න පිළිබඳ වැඩි විස්තරයකි. බොහෝ තනි මෙහෙයුම් එකම අවස්ථාවන්හිදී ප්‍රමාණවත් නොවන අතර එය බොහෝ අවස්ථාවන්හිදී වැදගත් නොවේ. නමුත් 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μ ක් පමණ එකතු කරයි. මෙහිදී මෙහෙයුමක් යනු ශරීරයේ දෝංකාරයක් , අංක ගණිත සංසන්දනයක්, වර්ධකයක් යනාදියයි. මේ කිසිවක් පුදුම සහගතද? එහි කාර්යය කිරීමට ලූප් උපකරණ සඳහා කොපමණ කාලයක් ගතවේදැයි සැලකිලිමත් වන්නේ කවුද - ධාවන කාලය ලූපයේ අන්තර්ගතය මගින් ආධිපත්‍යය දරයි.
බොබ්බෝගෝ

obbobbogo ඔබ හරි, එය ඇත්ත වශයෙන්ම මෙහෙයුම් ගණන ගැන ය. මෙය පිළිබිඹු කිරීම සඳහා මම මගේ පිළිතුර යාවත්කාලීන කළෙමි. අප කරන බොහෝ ඇමතුම් ඇත්ත වශයෙන්ම අප බලාපොරොත්තු වූවාට වඩා වැඩි මෙහෙයුම් ප්‍රමාණයක් සිදු කරයි. මා විසින් මෙහෙයවන ලද පරීක්ෂණ 50 ක පමණ ලැයිස්තුවකින් මම මෙය අඩු කළෙමි. මගේ පර්යේෂණය මෙම පිරිසට පවා අනවශ්‍ය බව මම අපේක්ෂා කළෙමි. සෑම විටම මෙන්, ඔබේ කේතීකරණ උත්සාහයන්ට ප්‍රමුඛතාවය දීමට මම යෝජනා කරමි: එය කෙටි කරන්න; එය කියවිය හැකි පරිදි සකසන්න; එය වේගවත් කරන්න; එය අතේ ගෙන යා හැකි කරන්න. බොහෝ විට # 1 හේතු වේ # 3. ඔබට අවශ්‍ය වන තෙක් # 4 වන කාලය නාස්ති නොකරන්න.
බ un නෝ බ්‍රොනොස්කි

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
මෙය තවත් කවචයක් බිහි කිරීමේ පොදු කාර්යයක් ඇත.
codeforester

1
ඇත්ත වශයෙන්ම, මෙය අතිරේක භයානක වන්නේ එය ප්‍රමාණවත් වන විට එය ෂෙල් වෙඩි 2 ක් බිහි කරන බැවිනි.
බ un නෝ බ්‍රොනොස්කි

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විචල්‍යය පරාසයේ අනෙක් පැත්තට වලංගු පරාසයක් වන "බුකෙන්ඩ්" නොවේ නම් අනපේක්ෂිත දෙයක් කරයි. නම් END=a, උදාහරණයක් ලෙස, දෝෂයක් ඇති නො වනු සහ සිදුකිරීමේදී පැවැත්වෙන කථා ඒ අයුරින්ම අගය {1..a}ප්රතිරාවය කරනු ඇත. මෙය Bash හි සුපුරුදු හැසිරීම ද වේ - එය බොහෝ විට අනපේක්ෂිත ය.

වියාචනය: සම්බන්ධිත කේතයේ කර්තෘ මම වෙමි.


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

මේ සියල්ල හොඳයි, නමුත් සීක් අවලංගු කර ඇති අතර බොහෝමයක් වැඩ කරන්නේ සංඛ්‍යාත්මක පරාසයන් සමඟ පමණි.

ඔබ ඔබේ ලූපය ද්විත්ව උපුටා දැක්වීම් සමඟ සම්බන්ධ කළහොත්, ඔබ නූල් දෝංකාර දෙන විට ආරම්භක සහ අවසාන විචල්‍යයන් අවලංගු වන අතර, ක්‍රියාත්මක කිරීම සඳහා ඔබට නූල නැවත බාෂ් වෙත යැවිය හැකිය. $is සමඟ පැන යා යුතුය, එබැවින් එය උප කුලකයට යැවීමට පෙර ඇගයීමට ලක් නොකෙරේ.

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

ඔබ ෂෙල් විධාන කරන්නේ නම් සහ ඔබට (මා වැනි) නල මාර්ගගත කිරීම සඳහා ish ලදායීතාවයක් තිබේ නම්, මෙය හොඳයි:

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

  • පළමුවැන්න අනුක්‍රමයේ ආරම්භක අංකයයි [අත්‍යවශ්‍ය නොවේ, පෙරනිමියෙන්: 1]
  • incr යනු වර්ධක වේ [අත්‍යවශ්‍ය නොවේ, පෙරනිමියෙන්: 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 අත්‍යවශ්‍ය නොවේ

පළමු හා අවසාන භාවිතා කිරීම

$ 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

PS: මගේ බැෂ්ටයට seqකෙසේ හෝ විධානයක් නැත.

මැක් ඕඑස්එක්ස් 10.6.8, බෑෂ් 3.2.48 හි පරීක්ෂා කර ඇත


0

මෙය Bash සහ Korn හි ක්‍රියාත්මක වන අතර ඉහළ සිට පහළ සංඛ්‍යා දක්වාද යා හැකිය. බොහෝ විට වේගවත් හෝ ලස්සන නැති නමුත් ප්‍රමාණවත් ලෙස ක්‍රියා කරයි. නිෂේධනයන් ද හසුරුවයි.

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"
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.