Mam dane wyjściowe, z VBoxManage list vms
których wygląda to tak:
"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}
Muszę złapać nazwy arch
i arch2
i zapisać je w zmiennej.
Mam dane wyjściowe, z VBoxManage list vms
których wygląda to tak:
"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}
Muszę złapać nazwy arch
i arch2
i zapisać je w zmiennej.
Odpowiedzi:
Spowoduje to przeanalizowanie zawartości tych 2 ciągów:
$ grep -o '".*"' somefile | sed 's/"//g'
arch
arch2
Powyższe wygląda na ciąg pasujący do wzoru ".*"
. To pasuje do wszystkiego, co występuje w obrębie podwójnych cudzysłowów. Więc grep
zwrócą te typy wartości:
"arch"
"arch2"
Rura do sed
usunie wszelkie podwójne cudzysłowy z tych ciągów, dając ciągi, których szukasz. Zapis sed 's/"//g'
jest instruowanie sed
zrobić wyszukiwania i zamiany na wszystkie wystąpienia cudzysłowach, zastępując je z niczego s/"//g
. Polecenie s/find/replace/g
jest tym, co się tam dzieje, a g
ciąg wyszukiwania służy do tego, aby zrobić to globalnie na całym podanym ciągu.
Możesz także użyć sed
do odcięcia początkowego podwójnego cytatu, zatrzymania tego, co jest między nimi, i odcięcia pozostałego cytatu + wszystkiego po nim:
$ sed 's/^"\(.*\)".*/\1/' a
arch
arch2
$ grep -o '".*"' somefile | tr -d '"'
arch
arch2
Polecenia tr
można używać do usuwania znaków. W tym przypadku usuwa podwójne cudzysłowy.
$ grep -oP '(?<=").*(?=")' somefile
arch
arch2
Korzystając grep
z funkcji PCRE możesz wyszukać dowolne podciągi, które zaczynają się od podwójnego cudzysłowu lub kończą podwójnym cudzysłowiem i zgłaszają tylko podłańcuchy.
/address/
do sed
jak sed '/^"\(arch[^"]*\)/s//\1/
będziesz pracować wyłącznie na liniach zawierających ten ciąg.
sed
naprawdę powinieneś robić s/^"\([^"]*\)".*/\1/
na wypadek, gdyby na linii były tylko dwa podwójne cudzysłowy.
To kolejna praca dla cut
:
VBoxManage list vms | cut -d \" -f2
cut
dzieli każdą linię na pola przy użyciu znaku cudzysłowu jako separatora, a następnie wypisuje pole 2: pole 1 jest pustym ciągiem przed pierwszym cytatem, pole 2 jest poszukiwanym ciągiem między cytatami, a pole 3 jest resztą linia.
Dzięki sed
niemu możesz:
var=$(VBoxManage list vms | sed 's/^"\([^"]*\).*/\1/')
Wyjaśnienie:
s/.../.../
- dopasuj i zamień^
- mecz na początku linii\(...\)
- jest to odniesienie wstecz, możemy odwołać się do tego, co jest tutaj dopasowane później \1
[^"]*
- dopasuj dowolną sekwencję, która nie zawiera "
(tj. do następnej "
).*
- dopasuj do reszty linii\1
- zastąpić referencją wstecznąLub z awk
:
var=$(VBoxManage list vms | awk -F\" '{ print $2 }')
Zauważ, że we współczesnych powłokach możesz także użyć tablicy zamiast normalnej zmiennej. W bash
można zrobić:
IFS=$'\n'; set -f
array=( $(VBoxManage list vms | awk -F\" '{ print $2 }') )
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"
To może być łatwiejsze, gdy przychodzi się do użycia zmiennej.
Używając bash, napisałbym:
while read vm value; do
case $vm in
'"arch"') arch=$value ;;
'"arch2"') arch2=$value ;;
esac
done < <( VBoxManage list vms )
echo $arch
echo $arch2
I ten przez grep oneliner z --perl-regexp
opcją,
VBoxManage list vms | grep -oP '(?<=^\")[^"]*'
Wyjaśnienie:
(?<=^\")[^"]*
-> Tutaj jest używany wygląd. Dopasowuje dowolny znak, ale nie "
zero lub więcej razy (gdy znajdzie podwójne cudzysłowy, przestaje się dopasowywać), które są tuż po podwójnych cudzysłowach (tylko wiersz zaczynający się od podwójnych cudzysłowów).
Kolejny brzydki włam sed
,
$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
arch
arch2
ponieważ regex ma tryby chciwości i chciwości, jeśli masz wiele celów w tej samej linii, nie wyodrębni się tak, jak chcesz. Linia:
"tom" is a cat, and "jerry" is a mouse.
Cel:
tom
jerry
Polecenie (tryb zachłanny):
grep -oP '".*"' name
Polecenie (tryb bez chciwości):
grep -oP '".*?"' name
tr -d \"
to kolejny sposób na usunięcie cytatów. (tr
zwykle tłumaczy jeden zestaw znaków na inny;-d
każe mu je po prostu usunąć).