如何从命令的输出中提取带引号的字符串的内容?

Har*_*van 36 scripting text-processing

我的输出VBoxManage list vms如下所示:

"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}   
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}  
Run Code Online (Sandbox Code Playgroud)

我需要抓住的名字arch,并arch2和它们保存到一个变量。

slm*_*slm 46

使用 grep + sed

这将解析这两个字符串的内容:

$ grep -o '".*"' somefile | sed 's/"//g'
arch
arch2
Run Code Online (Sandbox Code Playgroud)

以上查找匹配模式的字符串".*"。这将匹配双引号内出现的任何内容。所以grep将返回这些类型的值:

"arch"
"arch2"
Run Code Online (Sandbox Code Playgroud)

管道 tosed将从这些字符串中去除任何双引号,为您提供您正在寻找的字符串。该符号sed 's/"//g'指示sed对所有出现的双引号进行搜索和替换,用s/"//g. 命令s/find/replace/g是那里发生的事情,g搜索的结尾告诉它在给定的整个字符串上全局执行它。

只使用 sed

您还可以使用sed砍掉开头的双引号,保留它们之间的内容,并砍掉剩余的引号 + 后面的所有内容:

$ sed 's/^"\(.*\)".*/\1/' a
arch
arch2
Run Code Online (Sandbox Code Playgroud)

其他方法

$ grep -o '".*"' somefile | tr -d '"'
arch
arch2
Run Code Online (Sandbox Code Playgroud)

该命令tr可用于删除字符。在这种情况下,它正在删除双引号。

$ grep -oP '(?<=").*(?=")' somefile
arch
arch2
Run Code Online (Sandbox Code Playgroud)

使用grep的 PCRE 功能,您可以查找以双引号开头或以双引号结尾的任何子字符串,并仅报告子字符串。

  • 我刚刚意识到你的 `sed` 真的应该做 `s/^"\([^"]*\)".*/\1/` 以防万一该行只有两个双引号。 (2认同)

Sté*_*las 28

这是另一个工作cut

VBoxManage list vms | cut -d \" -f2
Run Code Online (Sandbox Code Playgroud)

  • 非常整洁!它是如何工作的:`cut` 使用引号作为分隔符将每一行分成多个字段,然后输出字段 2:字段 1 是第一个引号之前的空字符串,字段 2 是引号之间的所需字符串,字段 3 是该行的其余部分。 (4认同)

Gra*_*eme 8

有了sed你可以这样做:

var=$(VBoxManage list vms | sed 's/^"\([^"]*\).*/\1/')
Run Code Online (Sandbox Code Playgroud)

解释:

  • s/.../.../ - 匹配和替换
  • ^- 在行首匹配
  • \(...\) - 这是一个反向引用,我们稍后可以参考这里匹配的内容 \1
  • [^"]*- 匹配任何不包含 a 的序列"(即直到下一个"
  • .* - 匹配该行的其余部分
  • \1 - 替换为反向引用

或与awk

var=$(VBoxManage list vms | awk -F\" '{ print $2 }')
Run Code Online (Sandbox Code Playgroud)

请注意,在现代 shell 中,您还可以使用数组而不是普通变量。在bash你可以这样做:

IFS=$'\n'; set -f
array=( $(VBoxManage list vms | awk -F\" '{ print $2 }') )
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"
Run Code Online (Sandbox Code Playgroud)

当您开始使用变量时,这可能会更容易。


Avi*_*Raj 6

还有一个通过 grep oneliner 的--perl-regexp选项,

VBoxManage list vms | grep -oP '(?<=^\")[^"]*'
Run Code Online (Sandbox Code Playgroud)

解释:

(?<=^\")[^"]*-> 这里使用了一个lookbehind。它匹配任何字符,但不是"零次或多次(一旦找到双引号,它就停止匹配)就在双引号之后(仅以双引号开头的行)。

另一个丑陋的黑客sed

$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
arch
arch2
Run Code Online (Sandbox Code Playgroud)


gle*_*man 5

使用 bash,我会写:

while read vm value; do
    case $vm in
        '"arch"') arch=$value ;;
        '"arch2"') arch2=$value ;;
    esac
done < <( VBoxManage list vms )
echo $arch
echo $arch2
Run Code Online (Sandbox Code Playgroud)