2011-10-01 2 views
30

Tôi có một số công việc dơ bẩn, do đó, một tập lệnh Bash có vẻ là một lựa chọn tốt. Tôi là người mới đối với Bash, và kinh nghiệm khiến tôi cảm thấy thất vọng.Bash: đọc một tệp theo từng dòng và xử lý từng phân đoạn dưới dạng tham số cho các prog khác

Tệp mapfiles.txt bao gồm các dòng như sau. Mỗi dòng có bốn phân đoạn được phân tách bằng khoảng trắng. Mỗi phân đoạn đại diện cho một tham số đầu vào cho một tên chương trình bên ngoài 'prog'. Ví dụ, "cm19_1.png" là filename, "0001" của index, "121.422.481" các longitude, và "31.035.995" các .

File: mapfiles.txt

cm19_1.png 0001 121422481 31035995 
cm19_2.png 0002 121423224 31035995 
cm19_3.png 0003 121423967 31035995 
… 

Tôi muốn thực hiện các lệnh tương tự với từng ngành nghề. Như hình dưới đây, thứ tự tham số đầu vào của prog là hơi khác nhau. Vì vậy, nó có ý nghĩa để viết một kịch bản bash để xử lý công việc lặp đi lặp lại.

[Usage] prog <index> <longitude> <latitude> <filename> 
example: prog 0001 121422481 31035995 cm19_1.png 

Nói chung, các tập lệnh bash sẽ hoạt động theo cách này:

  1. đọc một dòng từ mapfiles.txt
  2. chia các phân đoạn
  3. Gọi prog với một trật tự thông số đúng

Đây là run.sh.

#!/bin/sh 

input=mapfiles.txt 
cmd=prog 

while read line 
do 
     file=$(echo $line | cut -d' ' -f1) 
     key=$(echo $line | cut -d' ' -f2) 
     log=$(echo $line | cut -d' ' -f3) 
     lat=$(echo $line | cut -d' ' -f4) 
     echo $cmd $key $log $lat $file 
done < "$input" 

gì tôi mong đợi là

prog 0001 121422481 31035995 cm19_1.png 
prog 0002 121423224 31035995 cm19_2.png 
prog 0003 121423967 31035995 cm19_3.png 
… 

Kết quả THỰC TẾ tôi nhận được

cm19_1.png21422481 31035995 
cm19_2.png21423224 31035995 
cm19_3.png21423967 31035995 

vấn đề mà nhầm lẫn tôi

  1. ở đâu 'prog'?
  2. Đâu là khoảng trắng?
  3. Có gì sai với thứ tự tham số?

Hmm… Tôi đã viết kịch bản này trên máy Mac bằng cách sử dụng vim và sao chép nó vào hộp Khoa học Linux và hộp gentoo. Ba chàng trai này có được kết quả tương tự vô lý.

+1

Không tái sản xuất ở đây. Tìm lỗi chính tả. Ngoài ra, thay vì tất cả các vết cắt chỉ sử dụng 'đọc tệp nhật ký khóa lat'. * UPD * xem câu trả lời. –

+0

Khi kết hợp với ssh trong vòng lặp, hãy xem câu hỏi này: http://stackoverflow.com/questions/9393038/ssh-breaks-out-of-while-loop-in-bash – Christian

Trả lời

42

Bạn có thể đơn giản hóa này rất nhiều:

while read file key log lat 
do 
    echo "$cmd" "$key" "$log" "$lat" "$file" 
done < "$input" 
+0

Điều gì là một mẹo đẹp và thanh lịch . –

+6

Bạn có thể đơn giản hóa nó hơn nữa. Bạn không cần biến riêng cho mỗi đối số: 'while read line; do echo $ cmd $ line; thực hiện <"$ đầu vào" ' – Idelic

2

prog có thể đã biến mất vì $cmd không xuất khẩu. Phiên bản/bin/sh của bạn có thể thực thi câu lệnh while trong một trình bao riêng biệt. Đây không phải là trường hợp, và đây không phải là trường hợp của tôi cài đặt bash, nhưng có lẽ bạn cư xử theo những cách thú vị trong bộ phận này.

UPD Tôi thấy rằng bạn có một số hộp mang lại kết quả tương tự. Điều này làm cho lý thuyết subshell khó xảy ra. Có lẽ bạn có một số nhân vật hài hước trong tập lệnh và/hoặc tệp nguồn của bạn.

Tôi đã sao chép và dán tập lệnh và tệp nguồn của bạn vào hộp gentoo và nó cho kết quả mong đợi. Có lẽ bạn nên làm như vậy, và so sánh các tập tin với bản gốc của bạn.

+2

Cảm ơn bạn rất nhiều. Bình luận của bạn giúp tôi tìm hiểu những gì thực sự sai. Nó không phải là Script Bash - Tôi thử nghiệm nó trên ba hộp khác nhau - đó là mapfiles.txt mà đi sai. Tệp được tạo trong Windows, kết thúc bằng^M ở mỗi dòng. Sau khi xóa^M, mọi thứ diễn ra tốt đẹp. –

8

Sử dụng GNU Song song bạn có thể làm điều đó trong một dòng duy nhất + bạn làm cho nó thực hiện song song miễn phí:

cat mapfile.txt | parallel --colsep '\s' prog {2} {3} {4} {1} 

Watch video giới thiệu để tìm hiểu thêm: http://www.youtube.com/watch?v=OpaiGYxkSuQ