Як витягнути вміст цитованих рядків з виводу команди?


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
ОДС - якщо додати /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 - рештою рядок.
дельтаб

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]}"

Це може бути простіше, коли ви приймете використовувати змінну.


Ви б розірвали цю команду sed для мене, будь ласка?
Гарріс Каван

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.