Eu tenho saída da VBoxManage list vms
qual se parece com isso:
"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}
Eu preciso pegar os nomes arch
e arch2
e guardá-las em uma variável.
Eu tenho saída da VBoxManage list vms
qual se parece com isso:
"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}
Eu preciso pegar os nomes arch
e arch2
e guardá-las em uma variável.
Respostas:
Isso analisará o conteúdo dessas duas strings:
$ grep -o '".*"' somefile | sed 's/"//g'
arch
arch2
O exemplo acima procura uma sequência que corresponda ao padrão ".*"
. Isso corresponderá a qualquer coisa que ocorra entre aspas duplas. Então grep
, retornará esses tipos de valores:
"arch"
"arch2"
O tubo para sed
retirar as aspas duplas dessas strings, fornecendo as strings que você está procurando. A notação sed 's/"//g'
está instruindo sed
a fazer uma pesquisa e a 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 rastreamento g
da pesquisa diz para fazê-lo globalmente em toda a cadeia que é fornecida.
Você também pode usar sed
para cortar a cotação dupla inicial, manter o que há entre elas e cortar a cotação restante + tudo o que há depois:
$ sed 's/^"\(.*\)".*/\1/' a
arch
arch2
$ grep -o '".*"' somefile | tr -d '"'
arch
arch2
O comando tr
pode ser usado para excluir caracteres. Nesse caso, está excluindo as aspas duplas.
$ grep -oP '(?<=").*(?=")' somefile
arch
arch2
Usando grep
o recurso PCRE, você pode procurar por substrings que começam com aspas duplas ou terminam com aspas duplas e relatam apenas a substring.
/address/
para sed
como sed '/^"\(arch[^"]*\)/s//\1/
você só vai operar em linhas que contenham essa string.
sed
realmente deveria estar fazendo s/^"\([^"]*\)".*/\1/
apenas no caso de haver apenas duas aspas duplas na linha.
Esse é outro trabalho para cut
:
VBoxManage list vms | cut -d \" -f2
cut
divide cada linha em campos usando as aspas como delimitador e, em seguida, gera o campo 2: o campo 1 é a sequência vazia antes da primeira cotação, o campo 2 é a sequência desejada entre as aspas e o campo 3 é o restante linha.
Com sed
você pode fazer:
var=$(VBoxManage list vms | sed 's/^"\([^"]*\).*/\1/')
Explicação:
s/.../.../
- combinar e substituir^
- partida no início da linha\(...\)
- esta é uma referência anterior, podemos nos referir ao que corresponde aqui mais tarde com \1
[^"]*
- corresponde a qualquer sequência que não contenha um "
(ou seja, até a próxima "
).*
- corresponder ao resto da linha\1
- substitua pela referência anteriorOu com awk
:
var=$(VBoxManage list vms | awk -F\" '{ print $2 }')
Observe que, nos shells modernos, você também pode usar uma matriz em vez 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.
Usando o bash, eu escreveria:
while read vm value; do
case $vm in
'"arch"') arch=$value ;;
'"arch2"') arch2=$value ;;
esac
done < <( VBoxManage list vms )
echo $arch
echo $arch2
E aquele através do grep oneliner com --perl-regexp
opção,
VBoxManage list vms | grep -oP '(?<=^\")[^"]*'
Explicação:
(?<=^\")[^"]*
-> Um lookbehind é usado aqui. Ele corresponde a qualquer caractere, mas não é igual a "
zero ou mais vezes (depois de encontrar aspas duplas, para de corresponder), logo após aspas duplas (apenas a linha que começa com aspas duplas).
Outro truque feio sed
,
$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
arch
arch2
como o regex possui modos ganancioso e não ganancioso, se você tiver vários destinos na mesma linha, ele não será extraído conforme desejado. Linha:
"tom" is a cat, and "jerry" is a mouse.
Alvo:
tom
jerry
Comando (modo ganancioso):
grep -oP '".*"' name
Comando (modo não ganancioso):
grep -oP '".*?"' name
tr -d \"
é outra maneira de excluir as aspas. (tr
Normalmente traduz um conjunto de caracteres em outra,-d
diz-lhe para apenas excluí-los em vez disso.)