2011-09-12 31 views
11
dpkg --list |grep linux-image |grep "ii " | while read line 
do 
    arr=(${line}) 
    let i=i+1 
    _constr+="${arr[2]} " 
done 
echo $i 
echo ${_constr} 

Các phát biểu echo bên ngoài vòng lặp không hiển thị các biến mong đợi. Làm cách nào để tạo nội dung của biến được truyền bên ngoài vòng lặp?Bash - tuyên truyền giá trị của biến đến bên ngoài vòng lặp

+6

Hãy nhớ rằng vòng lặp 'while' chạy trong một quá trình riêng biệt, đây là lý do bạn không thấy các biến đã thay đổi. –

+1

Sử dụng quá trình thay thế? –

Trả lời

19

Sự cố là đường ống chứ không phải vòng lặp. Hãy thử theo cách này

let i=0 
declare -a arr 

while read -r line ; do 
    arr=(${line}) 
    let i=i+1 
    _constr+="${arr[2]} " 
done < <(dpkg --list |grep linux-image |grep "ii ") 

echo $i 
echo ${_constr} 

Bạn cũng nên khai báo trước các hình cầu để rõ ràng, như minh họa ở trên.

Ống được thực hiện trong một vỏ bọc con, như được ghi chú bởi Blagovest trong bình luận của ông. Sử dụng process substitution instead (đây là cú pháp < <(commands)) giữ mọi thứ trong cùng một quá trình, do đó, các thay đổi đối với các biến toàn cầu là có thể.

Ngẫu nhiên, đường ống dẫn của bạn có thể được cải thiện cũng

dpkg --list |grep '^ii.*linux-image' 

Một ít gọi của grep phải lo lắng.

+0

Giải thích tuyệt vời. +1 –

+0

cảm ơn lời giải thích :-) – masuch

+0

Trong bash 3.x, dòng cuối cùng của vòng lặp phải giống như 'done <<< \' commands \ '' – Ida

3

này hơi by-đi câu hỏi của bạn (và đó là một câu hỏi hay), nhưng bạn có thể đạt được kết quả tương tự sử dụng đơn giản:

_constr=($(dpkg --list | awk '/^ii.*linux-image/{print $2}')) 

Các ($(cmd)) xây dựng initialises một mảng bash sử dụng đầu ra của lệnh trong vòng .

[[email protected]]$ echo ${_constr[*]} 
linux-image-2.6.35-22-generic linux-image-2.6.35-28-generic linux-image-generic 
[[email protected]]$ echo ${_constr[2]} 
linux-image-generic 

và bạn có thể nhận được số thành phần sử dụng ${#_constr[*]}.

[[email protected]]$ echo ${#_constr[*]} 
3 
+0

Cảm ơn rất nhiều :-) – masuch

+0

Đây thực sự là cách phù hợp để thực hiện. Tôi đã không có một hộp Debian để kiểm tra với hoặc tôi đã đề nghị cùng một điều. – Sorpigal

0

Ngoài ra, bạn có thể di chuyển các báo cáo tiếng vang bên trong subshell:

dpkg --list |grep linux-image |grep "ii " | (
    let i=0 
    declare -a arr 

    while read line 
    do 
    arr=(${line}) 
    let i=i+1 
    _constr+="${arr[2]} " 
    done 
    echo $i 
    echo ${_constr} 
) 

Lưu ý chèn các dấu ngoặc để xác định một cách rõ ràng nơi subshell bắt đầu và kết thúc.

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