J'ai une sortie de VBoxManage list vms
qui ressemble à ceci:
"Arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}
"Arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}
Je dois saisir les noms Arch
et Arch2
et les enregistrer dans une variable.
Cela analysera le contenu de ces 2 chaînes:
$ grep -o '".*"' somefile | sed 's/"//g'
Arch
arch2
Ce qui précède recherche une chaîne correspondant au modèle ".*"
. Cela correspondra à tout ce qui se produit entre guillemets doubles. Donc grep
renverra ces types de valeurs:
"Arch"
"Arch2"
Le canal vers sed
supprimera les guillemets doubles de ces chaînes, donnant ainsi les chaînes que vous recherchez. La notation sed 's/"//g'
demande à sed
d'effectuer une recherche et de remplacer toutes les occurrences de guillemets doubles, en les remplaçant par rien, s/"//g
. La commande s/find/replace/g
est ce qui se passe là-bas, et le dernier g
à rechercher lui dit de le faire globalement sur toute la chaîne qui lui est donnée.
Vous pouvez également utiliser sed
pour couper le guillemet double de début, conserver ce qu'il y a entre eux et couper le reste du devis + tout ce qu'il y a après:
$ sed 's/^"\(.*\)".*/\1/' a
Arch
arch2
$ grep -o '".*"' somefile | tr -d '"'
Arch
arch2
La commande tr
peut être utilisée pour supprimer des caractères. Dans ce cas, il supprime les guillemets doubles.
$ grep -oP '(?<=").*(?=")' somefile
Arch
arch2
En utilisant la fonction PCRE de grep
, vous pouvez rechercher toutes les sous-chaînes qui commencent par un guillemet double ou se terminent par un guillemet double et signaler uniquement la sous-chaîne.
C'est un autre travail pour cut
:
VBoxManage list vms | cut -d \" -f2
Avec sed
vous pouvez faire:
var=$(VBoxManage list vms | sed 's/^"\([^"]*\).*/\1/')
Explication:
s/.../.../
- correspondre et remplacer^
- correspond au début de la ligne\(...\)
- il s'agit d'une référence arrière, nous pouvons faire référence à ce qui est mis en correspondance ici plus tard avec \1
[^"]*
- correspond à toute séquence ne contenant pas de "
(C.-à-d. Jusqu'à la prochaine "
).*
- correspond au reste de la ligne\1
- remplacer par la référence arrièreOu avec awk
:
var=$(VBoxManage list vms | awk -F\" '{ print $2 }')
Notez que dans les shells modernes, vous pouvez également utiliser un tableau au lieu d'une variable normale. Dans bash
, vous pouvez faire:
IFS=$'\n'; set -f
array=( $(VBoxManage list vms | awk -F\" '{ print $2 }') )
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"
Cela pourrait être plus facile lorsque vous utilisez la variable.
Et celui via grep oneliner avec --Perl-regexp
option,
VBoxManage list vms | grep -oP '(?<=^\")[^"]*'
Explication:
(?<=^\")[^"]*
-> Un lookbehind est utilisé ici. Il correspond à n'importe quel caractère mais pas à "
zéro ou plusieurs fois (une fois qu'il trouve des guillemets doubles, il cesse de correspondre) qui sont juste après les guillemets doubles (uniquement la ligne qui commence par des guillemets doubles).
Un autre hack laid à travers sed
,
$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
Arch
arch2
En utilisant bash, j'écrirais:
while read vm value; do
case $vm in
'"Arch"') Arch=$value ;;
'"Arch2"') Arch2=$value ;;
esac
done < <( VBoxManage list vms )
echo $Arch
echo $Arch2
puisque regex a des modes gourmands et non gourmands, si vous avez plusieurs cibles sur la même ligne, il ne sera pas extrait comme vous le souhaitez. Ligne:
"tom" is a cat, and "jerry" is a mouse.
Cible:
tom
jerry
Commande (mode gourmand):
grep -oP '".*"' name
Commande (mode non gourmand):
grep -oP '".*?"' name