Como extraio o conteúdo de strings entre aspas da saída de um comando?

17

Eu tenho a saída de VBoxManage list vms , que é assim:

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

Eu preciso pegar os nomes arch e arch2 e salvá-los em uma variável.

    
por Harrys Kavan 13.06.2014 / 22:42

5 respostas

24

Usando grep + sed

Isso analisará o conteúdo dessas duas strings:

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

O texto acima procura por uma string que corresponda ao padrão ".*" . Isso corresponderá a qualquer coisa que ocorra entre aspas duplas. Portanto, grep retornará esses tipos de valores:

"arch"
"arch2"

O canal para sed removerá as aspas duplas dessas strings, fornecendo as strings que você está procurando. A notação sed 's/"//g' está instruindo sed para fazer uma pesquisa e substituir todas as ocorrências de aspas duplas, substituindo-as por nada, s/"//g . O comando s/find/replace/g é o que está acontecendo lá, e o trailing g to search diz para fazer isso globalmente em toda a string que é dada.

Usando apenas sed

Você também pode usar sed para cortar as aspas duplas iniciais, manter o que há entre elas e cortar a cotação restante + depois de tudo:

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

Outros métodos

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

O comando tr pode ser usado para excluir caracteres. Neste caso, está excluindo as aspas duplas.

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

Usando o recurso PCRE de grep , você pode procurar por substrings que começam com aspas duplas ou terminar com aspas duplas e relatar apenas a substring.

    
por 13.06.2014 / 22:49
19

Esse é outro trabalho para cut :

VBoxManage list vms | cut -d \" -f2
    
por 13.06.2014 / 23:43
7

Com sed , você pode fazer:

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

Explicação:

  • s/.../.../ - corresponde e substitui
  • ^ - corresponde no início da linha
  • \(...\) - esta é uma referência de volta, podemos nos referir ao que é combinado aqui mais tarde com
  • [^"]* - corresponde a qualquer sequência que não contenha " (ou seja, até o próximo " )
  • .* - corresponde ao resto da linha
  • - substitua pela referência anterior

Ou com awk :

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

Note que nos shells modernos você também pode usar um array ao invés de uma variável normal. Em bash você pode fazer:

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

Isso pode ser mais fácil quando você usa a variável.

    
por 13.06.2014 / 22:51
5

Usando bash, eu escrevia:

while read vm value; do
    case $vm in
        '"arch"') arch=$value ;;
        '"arch2"') arch2=$value ;;
    esac
done < <( VBoxManage list vms )
echo $arch
echo $arch2
    
por 13.06.2014 / 22:56
5

E o único através do greel oneliner com a opção --perl-regexp ,

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

Explicação:

(?<=^\")[^"]* - > Um lookbehind é usado aqui. Ele corresponde a qualquer caractere, mas não a " zero ou mais vezes (depois de encontrar aspas duplas, ele para de corresponder), que são logo após as aspas duplas (somente a linha que começa com aspas duplas).

Outro feio hackear sed

$ sed '/.*\"\(.*\)\".*/ s///g' file
arch
arch2
    
por 14.06.2014 / 02:45