Как извлечь содержимое строк в кавычках из вывода команды?


26

У меня есть выход, VBoxManage list vmsкоторый выглядит так:

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

Мне нужно , чтобы захватить имена archи arch2и сохранить их в переменную.

Ответы:


34

Использование grep + sed

Это проанализирует содержимое этих двух строк:

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

Вышесказанное ищет строку, соответствующую шаблону ".*". Это будет соответствовать всему, что встречается в двойных кавычках. Так grepчто вернет эти типы значений:

"arch"
"arch2"

Канал, по которому sedбудут отбрасываться любые двойные кавычки из этих строк, дает вам строки, которые вы ищете. Запись sed 's/"//g'инструктирует sedсделать поиск и замену на все случаи двойных кавычек, заменяя их ни с чем, s/"//g. Команда s/find/replace/g- это то, что там происходит, и трейлинг gк поиску подсказывает ей делать это глобально на всей заданной строке.

Используя просто sed

Вы также можете использовать, sedчтобы отрубить начальную двойную кавычку, сохранить то, что находится между ними, и отрубить оставшуюся кавычку + все, что есть после:

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

Другие методы

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

Команду trможно использовать для удаления символов. В этом случае он удаляет двойные кавычки.

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

Используя grepфункцию PCRE, вы можете искать любые подстроки, которые начинаются с двойной кавычки или заканчиваются двойной кавычкой, и сообщать только о подстроке.


1
tr -d \"это еще один способ удалить цитаты. ( trобычно переводит один набор символов в другой; -dвместо этого говорит просто удалить их.)
deltab

1
slm - если вы добавите /address/в sedлайк, sed '/^"\(arch[^"]*\)/s//\1/вы будете работать только со строками, содержащими эту строку.
mikeserv

1
@mikeserv - правда, не был уверен, насколько последовательной будет арка в его выводе. Но если это так, то это тоже сработает.
SLM

1
хорошая точка слм. Там нет никаких признаков того, что будет соответствовать. Сожалею.
mikeserv

2
Я только что понял, что вы sedдействительно должны делать s/^"\([^"]*\)".*/\1/на случай, если в строке будет только две двойные кавычки.
mikeserv

19

Это еще одна работа для cut:

VBoxManage list vms | cut -d \" -f2

3
Очень аккуратный! Как это работает: cutразбивает каждую строку на поля, используя знак кавычки в качестве разделителя, затем выводит поле 2: поле 1 - пустая строка перед первой кавычкой, поле 2 - искомая строка между кавычками, а поле 3 - остальная часть линия.
Deltab

7

С sedвами можно сделать:

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

Объяснение:

  • s/.../.../ - сопоставить и заменить
  • ^- совпадение в начале строки
  • \(...\) - это обратная ссылка, мы можем сослаться на то, что здесь соответствует \1
  • [^"]*- сопоставить любую последовательность, которая не содержит "(т.е. до следующей ")
  • .* - соответствовать остальной части линии
  • \1 - заменить на обратную ссылку

Или с awk:

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

Обратите внимание, что в современных оболочках вы также можете использовать массив вместо обычной переменной. В bashвы можете сделать:

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

Это может быть проще, когда вы используете переменную.


Не нарушите ли вы эту команду, пожалуйста?
Гаррис Каван

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

5

И один через grep oneliner с --perl-regexpопцией,

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

Объяснение:

(?<=^\")[^"]*-> Взгляд здесь используется. Он соответствует любому символу, но не "ноль или более раз (как только он находит двойные кавычки, он прекращает сопоставление), которые идут сразу после двойных кавычек (только строка, которая начинается с двойных кавычек).

Еще один уродливый взлом sed,

$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
arch
arch2

0

Так как регулярные выражения имеют жадные и не жадные режимы, если у вас есть несколько целей на одной строке, он не будет извлекаться, как вы хотите. Линия:

"tom" is a cat, and "jerry" is a mouse. 

Цель:

tom
jerry

Команда (жадный режим):

grep -oP '".*"' name

Команда (не жадный режим):

grep -oP '".*?"' name
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.