実行中のVMをループして、引用符の間にあるものだけを返したい。
したがって、このコマンド:
VBoxManage list runningvms
戻り値:
"UbuntuServer" {7ef01f8d-a7d5-4405-af42-94d85f999dff}
そして、私はそれを返すことだけを望んでいます:
UbuntuServer
これは私がこれまでに持っているものです(失敗):
#!/bin/bash
for machine in `cat VBoxManage list runningvms`; do
echo "$machine"
done
exit
警告:VMの名前にシェルグロブ文字が含まれている場合、またはスペースが含まれている場合、これはすべて危険です。
実行中のVMが1つしかない場合は、次のように実行できます。
read machine stuff <<< $(VBoxManage list runningvms)
echo "$machine"
Bash配列の代替(同じ条件):
vbm=($(VBoxManage list runningvms))
echo "${vbm[0]}"
そのプログラムが複数の行を返す場合、より古典的なアプローチは次のようになります。
for machine in $(VBoxManage list runningvms|cut -d" " -f 1); do
echo "$machine"
done
VBoxManage list runningvms | cut -d '"' -f 2 | while read machine; do
echo "$machine"
done
ワンライナーファンの場合:
VBoxManage list runningvms | cut -d" " -f 1 | grep -oP "(?<=\").*(?=\")"
読みながら各行を検証するには、正規表現を記述し、BASH_REMATCH
を使用してそこから一致グループを抽出するのが安全な方法です。
次のコードで:
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)
...そしてVBoxManageの次のモック実装(VirtualBoxを持たない人々がテストを再現できるようにするため):
VBoxManage() { printf '%s\n' '"UbuntuServer" {7ef01f8d-a7d5-4405-af42-94d85f999dff}'; }
...出力は次のとおりです。
Found VM with name UbuntuServer and uuid 7ef01f8d-a7d5-4405-af42-94d85f999dff
このアプローチの利点に注意してください。
*
という名前の仮想マシンでは、その名前が現在のディレクトリ内のファイルの名前にサイレントに置き換えられることはありません)。sed
、cut
、&c。などのシェル外部のツールは含まれませんが、シェルに組み込まれた機能のみに依存します。 BashFAQ#1 を参照してください。 while read
の使用を文書化する、および 正規表現マッチングに関するbash-hackersのwiki[[ $string =~ $re ]]
を文書化する。VBoxManage list runningvms | sed 's/"//g;s/ .*//'
ループするには:
for machine in `VBoxManage list runningvms | sed 's/"//g;s/ .*//'` ; do
echo $machine
done
マシンの名前にスペースがある場合、これは壊れます。