2011-08-15 6 views
15

Tôi muốn lặp qua máy ảo đang chạy của mình và chỉ trả về những gì nằm giữa dấu ngoặc kép.Lấy danh sách các máy ảo đang chạy bằng cách sử dụng VBoxManage

Vì vậy, lệnh này:

VBoxManage list runningvms 

lợi nhuận:

"UbuntuServer" {7ef01f8d-a7d5-4405-af42-94d85f999dff} 

Và tôi chỉ muốn nó trở lại:

UbuntuServer 

Đây là những gì tôi có cho đến nay (thất bại):

#!/bin/bash 
for machine in `cat VBoxManage list runningvms`; do 
     echo "$machine" 
done 
exit 

Trả lời

16

Cảnh báo: tất cả điều này là nguy hiểm nếu tên máy ảo của bạn có các ký tự kết xuất vỏ trong chúng hoặc chứa dấu cách.


Bạn có thể làm một cái gì đó như thế này nếu chỉ có một chạy VM:

read machine stuff <<< $(VBoxManage list runningvms) 
echo "$machine" 

Alternative với mảng bash (cùng điều kiện):

vbm=($(VBoxManage list runningvms)) 
echo "${vbm[0]}" 

Nếu chương trình trả nhiều hơn một dòng, một cách tiếp cận cổ điển hơn sẽ là:

for machine in $(VBoxManage list runningvms|cut -d" " -f 1); do 
    echo "$machine" 
done 
+0

Cách tiếp cận "cổ điển" là thực hành không tốt, cũng như phương pháp 'mảng = ($ (...))'; cả hai, ví dụ, sẽ thay thế một mã thông báo duy nhất '*' trong đầu vào của bạn bằng một danh sách các tệp trong thư mục hiện tại. Xem [Don't Read Lines With For] (http://mywiki.wooledge.org/DontReadLinesWithFor), [BashPitfalls # 50] (http://mywiki.wooledge.org/BashPitfalls#hosts.3D.28_.24.28aws_ … 29_.29) và [BashFAQ # 1] (http://mywiki.wooledge.org/BashFAQ/001) –

+0

Cần tách từ cho ví dụ cụ thể này và tên VM khớp với mẫu hình cầu có vẻ không chắc. – Mat

+0

Sự kiện mất dữ liệu tồi tệ nhất mà tôi có mặt đã xảy ra vì ai đó đã bỏ qua một sự kiện "không thể" (một chương trình tạo tệp "không thể bao giờ" tạo ra bất kỳ thứ gì không khớp với [0-9a-f] {24}; trong thư viện của bên thứ ba đã làm hỏng một con trỏ, đổ rác ngẫu nhiên đã xảy ra để bao gồm một khoảng trắng được bao quanh '*' vào bộ đệm được sử dụng cho tên ... và một kịch bản shell lặp qua tên tệp đến tuổi ra khỏi hệ thống sao lưu rồi xóa *mọi điều*). –

0
VBoxManage list runningvms | sed 's/"//g;s/ .*//' 

Để lặp qua:

for machine in `VBoxManage list runningvms | sed 's/"//g;s/ .*//'` ; do 
    echo $machine 
done 

này sẽ phá vỡ nếu máy của bạn có khoảng trống trong tên của nó.

+0

Xem [Don't Read Lines With For] (http://mywiki.wooledge.org/DontReadLinesWithFor) –

15
VBoxManage list runningvms | cut -d '"' -f 2 | while read machine; do 
    echo "$machine" 
done 
+1

Đó là tốt hơn so với mỏ của tôi sẽ thất bại nếu tên hình ảnh có không gian trong đó ... đã không nghĩ về điều đó . – Mat

+1

Cú pháp 'while read ... do' chính xác là những gì tôi đang tìm kiếm! – Kyrstellaine

+1

Bạn có thể lấy ra 'cắt' bằng cách viết 'trong khi IFS ='" 'đọc _ máy _; do'. –

2

cho người hâm mộ một liner:

VBoxManage list runningvms | cut -d" " -f 1 | grep -oP "(?<=\").*(?=\")" 
1

Để xác nhận mỗi dòng khi bạn đọc nó, cách an toàn để làm điều này là để viết một biểu thức chính quy và sử dụng BASH_REMATCH để trích xuất các nhóm phù hợp với từ nó .

Với đoạn mã sau:

re='^"(.*)" [{]([0-9a-f-]+)[}]$' 
while read -r line; do 
    if [[ $line =~ $re ]]; then 
    name=${BASH_REMATCH[1]}; uuid=${BASH_REMATCH[2]} 
    echo "Found VM with name $name and uuid $uuid" >&2 
    else 
    echo "ERROR: Could not parse line: $line" >&2 
    fi 
done < <(VBoxManage list runningvms) 

... và thực hiện mô hình sau đây của VBoxManage (để cho phép folks mà không cần VirtualBox để tạo lại thử nghiệm):

VBoxManage() { printf '%s\n' '"UbuntuServer" {7ef01f8d-a7d5-4405-af42-94d85f999dff}'; } 

... đầu ra là như sau:

Found VM with name UbuntuServer and uuid 7ef01f8d-a7d5-4405-af42-94d85f999dff 

Lưu ý các ưu điểm của phương pháp này:

  • Nó không đưa ra các giả định vô căn cứ, chẳng hạn như loại trừ các máy ảo có khoảng trống hoặc các ký tự trích dẫn trong tên của chúng khỏi sự hỗ trợ.
  • Phát hiện bất kỳ dòng nào không phù hợp với mẫu dự kiến, thay vì hành xử theo cách không lường trước khi có các giá trị như vậy.
  • Nó vẫn hoạt động chính xác với dữ liệu mà thực hiện khớp với mẫu nhưng có giá trị không xác định. (Ví dụ: một máy ảo có tên * sẽ không thay thế tên đó bằng tên của tệp trong thư mục hiện tại).
  • Nó không liên quan đến các công cụ bên ngoài để vỏ như sed, cut, & c, nhưng dựa hoàn toàn vào chức năng vỏ BUILTIN -. Thấy BashFAQ #1 ghi lại việc sử dụng while read, và the bash-hackers' wiki on regular expression matching ghi [[ $string =~ $re ]].