به طور معمول، چند روش برای حل مشکل موجود است، هریک با مزایا و معایب خاص خود.
Bash نگارش 4 صفرهای پُرکننده(صفر قبل از عدد) و دامنه آنها را در بسط ابرویش مجاز میدارد:
# Bash 4 echo {01..10} for i in {01..10}; do ...
تمام چاره کارهای دیگر در این صفحه Bash قبل از نگارش 4.0، یا پوستههای غیر از Bash را فرض خواهد نمود.
اگر تعداد اعداد زیاد نیست، بسط ابرو میتواند به کار برود:
# Bash for i in 0{1,2,3,4,5,6,7,8,9} 10 do echo $i done
در Bash نگارش 3، میتوانید دامنهها را داخل بسط ابرو به کار ببرید(اما صفر پُرکننده را خیر). بنابراین همان کارمیتواند به طور مختصرتری به این شکل انجام بشود:
# Bash 3 for i in 0{1..9} 10 do echo $i done
مثال دیگر، برای خروجی 0000 تا 0034:
# Bash 3 for i in {000{0..9},00{10..34}} do echo $i done # .ابروهای خارجی فقط به جای اضافه کردن آنها یکی پس از دیگری است # :استفاده از بسط را اجازه میدهد، به طور نمونه، مانند این wget 'http://foo.com/adir/thepages'{000{0..9},00{10..34}}'.html'
برخی شاید روش سریع و نامنزه زیر را ترجیح بدهند(برای تولید "000" تا "015"):
# Bash 3 for i in {1000..1015} do echo "${i:1}" # یا "${i#1}" # (مترجم: در اینجا از بسط پارامتر استفاده گردیده است) done
این برای توالی وسیع کسل کننده میشود، اما روشهای دیگری نیز وجود دارد. اگر فرمان printf را(که یک فرمان داخلی Bash است و استاندارد POSIX نیز هست) دارید، میتواند برای قالببندی عدد به کار برود:
# Bash for ((i=1; i<=10; i++)) do printf "%02d " "$i" done
همچنین، چون printf به طور ضمنی حلقه است، اگر شناسههایی غیر از مشخص کننده قالب داده شده باشد، میتوانید به طورهنگفتی این را مختصر نمایید:
# Bash 3 printf "%03d\n" {1..300}
اگر از قبل مقدار شروع و خاتمه را نمیدانید:
# Bash 3 # متغیرهای شامل عدد صحیح میباشند end و start eval printf '"%03d\n"' {$start..$end}
فرمان eval در اینجا لازم است، زیرا نمیتوانید در بسط ابرو متغیرها را داشته باشید --فقط ثابتها.نقلقولهای اضافی را eval لازم دارد برای اینکه \n ما به یک n تغییر نکند. قدر مسلم روش eval راه حل شلوغی است، لطفاً برای مقاصد خطیر به جای آن از حلقه for استفاده کنید.
در پوسته Korn فرمان typeset دارای گزینهای برای تعیین تعداد ارقام عدد میباشد:
# Korn $ typeset -Z3 i=4 $ echo $i 004
اگر فرمان seq(1) در دسترس باشد( بخشی از GNU sh-utils/coreutils میباشد)، میتوانید به این شکل از آن استفاده کنید:
seq -w 1 10
یا، برای تعداد ارقام دلخواه همراه با صفرهای پشت عدد(در اینجا: 3):
seq -f "%03g" 1 10
با ترکیب printf با seq(1)، میتوانید موردی مانند این را انجام بدهید:
# POSIX shell, GNU utilities printf "%03d\n" $(seq 300)
(که شاید اگر از Bash استفاده نمیکنید، اما seq(1) را دارید و نگارش seq(1) شما فاقد مشخص کننده قالب سَبک printf است، این روش مفید باشد. یک مجموعه عجیبی از محدودیتهامیباشد، اماگمان میکنم به طور نظری ممکن باشد. چون seq ابزار خارجی غیر استانداردی است، خوب است انتخابهای شما باز باشد.)
آگاه باشید که به هرحال آن کاربرد seq میتواند به عنوان شیوه نامساعدی مطرح شده باشد، حتی در بخش هرگز این موارد را انجام ندهید اشاره شده است.
بعضی سیستمهای مشتق شده از BSD در عوض seq(1)دارای jot(1) میباشند. مطابق رسم خیلی خوب یونیکس، این یک ترکیب دستوری کاملاً ناسازگاری دارد:
# POSIX shell, OpenBSD et al. printf "%02d\n" $(jot 10 1) # Bourne shell, OpenBSD (at least) jot -w %02d 10 1
سرانجام، مثال ذیل که با هرپوسته مشتق شده از شل Bourne (که هم expr و هم sed را دارد) با سه بایت برای هر عدد در هر سطر و صفر قبل از عدد در صورت لزوم، کار میکند:
# Bourne i=0 while test $i -le 10 do echo "00$i" i=`expr $i + 1` done | sed 's/.*\(...\)$/\1/g'
در این مثال، تعداد '.' داخل پرانتزها در فرمان sed تعیین میکند چند بایت از فرمان echo (در انتهای هر سطر) حفظ و چاپ خواهد شد.
اما اگر به راستی میخواهید به یک فرمان خارجی یونیکس استناد کنید، در درجه اول میتوانید تمام آن را به خوبی با awk انجام بدهید:
# Bourne # شامل یک عدد صحیح است count متغیر awk -v count="$count" 'BEGIN {for (i=1;i<=count;i++) {printf("%03d\n",i)} }' # بیفایده awk با سولاریس سالخورده و Bourn awk "BEGIN {for (i=1;i<=$count;i++) {printf(\"%03d\\n\",i)} }"
اکنون، چون دلیل شماره یک پرسیدن این سؤال برای بارگیری تصویرها به طور انبوه است، میتوانید مثالهای فوق را با xargs(1) و wget(1) برای واکشیدن فایلها به کار ببرید:
almost any example above | xargs -i% wget $LOCATION/%
فرمان xargs -i% در هر نوبت سطری از ورودی را میخواند، و % انتهای فرمان را با ورودی تعویض میکند.
یا، مثال سادهتر که به کاربردن حلقه forاست:
# Bash 3 for i in {1..100}; do wget "$prefix$(printf %03d $i).jpg" sleep 5 done
یا، برای اجتناب از پوستههای فرعی( bash نگارش 3.1 لازم دارد):
# Bash 3.1 for i in {1..100}; do printf -v n %03d $i wget "$prefix$n.jpg" sleep 5 done
پرسش و پاسخ 18 (آخرین ویرایش 2012-02-01 16:00:55 توسط GreyCat)