2010-03-18 52 views
9

Tôi đã viết một tệp .sh để biên dịch và chạy một vài chương trình cho bài tập về nhà. Tôi có một "cho" vòng lặp trong kịch bản, nhưng nó sẽ không làm việc trừ khi tôi chỉ sử dụng số nguyên:Vòng lặp bằng cách sử dụng các số nguyên không?

#!/bin/bash 
for ((i=10; i<=100000; i+=100)) 
do 
    ./hw3_2_2 $i 
done 

Biến $ i là một đầu vào cho hw3_2_2 chương trình, và tôi có giá trị không nguyên tôi muốn sử dụng. Làm thế nào tôi có thể lặp lại thông qua việc chạy mã với một danh sách các số thập phân?

Trả lời

9

Cách đơn giản nhất là chỉ cần liệt kê chúng:

for a in 1.2 3.4 3.11 402.12 4.2 2342.40 
do 
    ./hw3_2_2 $a 
done 

Nếu danh sách là rất lớn, vì vậy bạn không thể có nó như là một danh sách đen, hãy xem xét bán phá giá nó trong một tập tin và sau đó sử dụng một cái gì đó giống như

for a in $(< my-numbers.txt) 
do 
    ./hw3_2_2 $a 
done 

Phần $ (< my-numbers.txt) là một cách hiệu quả (trong Bash) để thay thế nội dung của tệp tên ở vị trí của tập lệnh. Nhờ Dennis Williamson đã chỉ ra rằng không cần sử dụng lệnh bên ngoài cat cho việc này.

+2

sử dụng vô dụng của 'cat'. Trong Bash: '$ (

+0

@ Dennis: đúng, tôi sẽ sửa. Cảm ơn. – unwind

0

bash không làm số thập phân. Hoặc sử dụng một cái gì đó như bc có thể hoặc chuyển sang ngôn ngữ lập trình hoàn chỉnh hơn. Hãy coi chừng accuracy problems.

1

Dưới đây là một cách khác. Bạn có thể sử dụng một doc vào đây để bao gồm dữ liệu của bạn trong kịch bản:

read -d '' data <<EOF 
1.1 
2.12 
3.14159 
4 
5.05 
EOF 

for i in $data 
do 
    ./hw3_2_2 $i 
done 

Tương tự:

array=(
1.1 
2.12 
3.14159 
4 
5.05 
) 

for i in ${array[@]} 
do 
    ./hw3_2_2 $i 
done 
8

bạn có thể sử dụng awk để tạo thập phân của bạn ví dụ như bước 0.1

num=$(awk 'BEGIN{for(i=1;i<=10;i+=0.1)print i}') 
for n in $num 
do 
    ./hw3_2_2 $n 
done 

hoặc bạn có thể làm điều đó hoàn toàn trong awk

awk 'BEGIN{cmd="hw3_2_2";for(i=1;i<=10;i+=0.1){c=cmd" "i;system(cmd) } }' 
+1

Thực tế xấu khi sử dụng dấu phẩy động trong các vòng lặp như vậy bởi vì nếu bạn tiếp tục thêm 0,1 đến 1, bạn sẽ không bao giờ nhận được 10. Bộ đếm sẽ chuyển từ thứ gì đó như 9.9999999999999822 thành 10.099999999999982. – Gabe

+0

bạn đã thử chưa? hãy thử và sau đó cho tôi biết nếu nó sẽ nhận được đến 10. – ghostdog74

+0

Nếu bạn thay đổi '<= 10' thành' <10' bạn mong đợi đầu ra sẽ thay đổi, phải không? Phải không? – Gabe

22

Tôi thấy ngạc nhiên là trong năm năm không ai đề cập đến tiện ích được tạo ra chỉ để tạo ra dãy, nhưng, một lần nữa, nó xuất phát từ BSD khoảng năm 2005, và có lẽ nó thậm chí không có sẵn trên Linux vào thời điểm đặt câu hỏi được làm từ.

Nhưng ở đây nó là:

for i in $(seq 0 0.1 1) 

Hoặc, để in tất cả các số có cùng chiều rộng (bằng cách thêm vào trước hoặc nối zero), sử dụng -w. Điều đó giúp ngăn các số được gửi dưới dạng "số nguyên", nếu điều đó có thể gây ra sự cố.

Cú pháp là seq [first [incr]] last, với first mặc định là 1, và incr mặc định cho 1 hoặc -1, tuỳ thuộc vào việc last là lớn hơn hoặc ít hơn first. Để biết các thông số khác, hãy xem seq(1).

+0

Điều này chắc chắn là câu trả lời đúng! – rhombidodecahedron

+0

Xin chào Daniel, có cách nào để tăng x.x.x này cho vòng lặp không? Ví dụ: với i bằng $ (seq 1.0.20 0.0.1 1.0.24). Hoặc là có một cách để tăng phiên bản này # và thêm nó vào một danh sách để tôi có thể sử dụng nó trong vòng lặp? Cảm ơn! – user1164061

0

Tôi thường cũng sử dụng "seq" theo câu trả lời thứ hai, nhưng chỉ để đưa ra một câu trả lời về một số nguyên vòng lặp chính xác mạnh mẽ và sau đó bc chuyển đổi sang một float:

#!/bin/bash 

for i in {2..10..2} ; do 
    x=`echo "scale=2 ; ${i}/10" | bc` 
    echo $x 
done 

cho:

.2 .4 .6 .8 1,0

Các vấn đề liên quan