web-dev-qa-db-ja.com

awkを使用して異なる文字間の文字列を抽出する

VirtualBox VMのUUIDを取得するbash関数を記述しようとしています。私はawkにかなり慣れているので、それを使用して問題を解決する方法を学ぶことに集中しようとしています。これを解決するためにsedまたはcutを使用できることを知っています。

_VBoxManage list vms_からの「生の」出力は次のとおりです。

_$ VBoxManage list vms
"FreeBSD" {1aac7062-bd59-47ee-9261-2f6aa8d9ef53}
"Windows 10" {64942de7-beb9-418c-9f52-5befcb6f577b}
"High Sierra" {07f73e1a-a0c4-4190-ade1-79a2e432b4d6}
"Test Machine" {9d0953a7-ca2a-4667-8c5b-1a9f550b2956}
_

私の望ましい出力は、特定のVMのUUIDを取得することです。この場合、「テストマシン」を使用して、_9d0953a7-ca2a-4667-8c5b-1a9f550b2956_を探しています(括弧_{_および_}_なし)。

かなりの検索とテストの後、私は思いついた

_$ VBoxManage list vms | awk '/Test Machine/{ sub("{" ,""); sub("}", "");  print $3 }'

9d0953a7-ca2a-4667-8c5b-1a9f550b2956 
_

それは動作しますが、それを抽出するためにsubコマンドを使用する必要があります。


私の質問は、or型の演算子を使用してアクションのsubstitution部分を簡略化する方法があるので、 2つのsubコマンドを使用する必要はありませんか?

たとえば、awk '/Test Machine/{ sub("{" || "}", ""); print $3'を試しても機能しません-角かっこを含むフィールド全体が出力されます。

_ {9d0953a7-ca2a-4667-8c5b-1a9f550b2956}
_

その文字列を抽出するより良い方法はありますか?

3
Allan

awkの-Fフィールドセパレータ。ここでは、2つのフィールド区切り記号を使用しています。 ({または}のいずれか)

VBoxManage list vms | awk -F"[{}]" '/Test Machine/{print $2}' 
7
Kamaraj

別の方法。

VBoxManage list vms | awk -F ' ' '{print substr($2, 2, length($2) - 2)}'

空のスペースでフィールドを区切る

awk -F ' '

最初の{と最後の}文字を削除して2列目を印刷する

'{print substr($2, 2, length($2) - 2)}'
3
Paulo Tomé

Gnu grepを使用(Perl-stye regexを使用):

grep -Po "(?<={)[a-f0-9-]+(?=})" 

...つまり、16進数字とダッシュのシーケンスで、左中括弧の直後、直後に右中括弧が続きます。

単純なgrepを使用

grep -Eo "([a-f0-9-]+-){4}[a-f0-9-]+"

...つまり、ダッシュで区切られた5桁の16進数。

2
xenoid
$ VBoxManage showvminfo 'Test Machine' --machinereadable | sed -n '/^UUID=/{ s///; s/"//gp; }'
1ce7ffef-8faa-4138-9b92-466698762f62

list vmsサブコマンドを使用する代わりに、サブコマンドshowvminfoを使用して、特定のマシンに関するすべての情報を取得します(ここではVMと呼ばれますTest Machine)。--machinereadableを使用すると、データを簡単に解析できる形式で出力します。VMのUUIDは次のように出力されます

UUID="1ce7ffef-8faa-4138-9b92-466698762f62"

sedコマンドが検出します。 UUID=ビットとすべての二重引用符を削除し、残っているものをすべて出力します。

sedコマンドは、さまざまな方法で記述できます。バリエーションは、例えば、

sed -n 's/^UUID="\(.*\)"$/\1/p'
0
Kusalananda

ここに私がPEを使用してそれを行う方法がありますおよびbash構文。

while read -r vmname uuid; do
  uuid=${uuid##*'{'}
  uuid=${uuid%'}'*}
  vmname=${vmname#*'"'}
  vmname=${vmname%'"'*}
  printf '%-15s %s\n' "$vmname" "$uuid"
done < <(VBoxManage list vms)

テストを使用してループ内でvmsを開始するか、出力を配列などに保存できます。また、VM名の名前に{または}が含まれている場合でも安全です。 2013年以降、スクリプトでそのコードを使用しています:-)

0
Jetchisel
  VBoxManage list vms|  awk -F "{" '/Test Machine/{gsub("}","",$NF);print $NF}'

出力

9d0953a7-ca2a-4667-8c5b-1a9f550b2956
0