web-dev-qa-db-ja.com

コマンドの出力から引用文字列の内容を抽出するにはどうすればよいですか?

次のようなVBoxManage list vmsからの出力があります。

"Arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}   
"Arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}  

ArchArch2という名前を取得して、変数に保存する必要があります。

27
Harrys Kavan

Grep + sedの使用

これにより、これら2つの文字列の内容が解析されます。

$ grep -o '".*"' somefile | sed 's/"//g'
Arch
arch2

上記は、パターン".*"に一致する文字列を探します。これは、二重引用符で囲まれたものと一致します。したがって、grepは次のタイプの値を返します。

"Arch"
"Arch2"

sedへのパイプは、これらの文字列から二重引用符を取り除き、探している文字列を提供します。表記sed 's/"//g'は、すべての二重引用符を検索して置換するようにsedに指示し、それらを何もないs/"//gに置き換えます。コマンドs/find/replace/gはそこで行われていることであり、検索する末尾のgは、指定された文字列全体に対してグローバルに実行するように指示します。

Sedだけを使う

sedを使用して、最初の二重引用符を削除し、その間にあるものを保持し、残りの引用符とその後のすべてを削除することもできます。

$ sed 's/^"\(.*\)".*/\1/' a
Arch
arch2

その他の方法

$ grep -o '".*"' somefile | tr -d '"'
Arch
arch2

コマンドtrを使用して、文字を削除できます。この場合、それは二重引用符を削除しています。

$ grep -oP '(?<=").*(?=")' somefile
Arch
arch2

grepのPCRE機能を使用すると、二重引用符で始まるか二重引用符で終わるすべての部分文字列を検索して、部分文字列のみを報告できます。

39
slm

これはcutの別の仕事です。

VBoxManage list vms | cut -d \" -f2
21

sedを使用すると、次のことができます。

_var=$(VBoxManage list vms | sed 's/^"\([^"]*\).*/\1/')
_

説明:

  • _s/.../.../_-一致して置換
  • _^_-行頭で一致
  • \(...\)-これは後方参照です。後で_\1_を使用して、ここで一致するものを参照できます
  • _[^"]*_-_"_を含まないシーケンスに一致します(つまり、次の_"_まで)
  • _.*_-残りの行に一致
  • _\1_-後方参照に置き換えます

またはawkを使用:

_var=$(VBoxManage list vms | awk -F\" '{ print $2 }')
_

最近のシェルでは、通常の変数の代わりに配列を使用することもできます。 bashでは、次のことができます。

_IFS=$'\n'; set -f
array=( $(VBoxManage list vms | awk -F\" '{ print $2 }') )
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"
_

これは、変数を使用するときに簡単になります。

7
Graeme

そして、--Perl-regexpオプション付きのgrep onelinerを使用したもの、

VBoxManage list vms | grep -oP '(?<=^\")[^"]*'

説明:

(?<=^\")[^"]*->後読みがここで使用されています。二重引用符(二重引用符で始まる行のみ)の直後にある任意の文字に一致しますが、"のゼロ回以上一致しません(二重引用符が見つかると一致しなくなります)。

sedによるもう1つの醜いハック

$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
Arch
arch2
6
Avinash Raj

Bashを使用して、次のように記述します。

while read vm value; do
    case $vm in
        '"Arch"') Arch=$value ;;
        '"Arch2"') Arch2=$value ;;
    esac
done < <( VBoxManage list vms )
echo $Arch
echo $Arch2
5
glenn jackman

regexには貪欲モードと非貪欲モードがあるため、同じ行に複数のターゲットがある場合、希望どおりに抽出されません。ライン:

"tom" is a cat, and "jerry" is a mouse. 

目標:

tom
jerry

コマンド(貪欲モード):

grep -oP '".*"' name

コマンド(非貪欲モード):

grep -oP '".*?"' name
0
Tiina