LinuxForum.Fans
Тема

Извлечение подстроки

Автор: xxblx 7 сообщений 2998 просмотров
12.11.2014 19:19 · отредактировано #400659

Доброго времени суток.

Необходимо извлечь подстроку.

Есть тарболл (*.tar.gz), в нем "бекап" системы установленной в chroot. Система была установлена (условно) в /mnt/mag.
В архиве, соответственно файлы с путями начиная от корня, но без слеша, т.к. архив рассчитан на последующее извлечение в /

Как это выглядит:

text
[xxblx@localhost mageia-chroot]$ tar -tf Mageia4_i586.tar.gz | grep -m 15 -E ".*" 
mnt/mag/
mnt/mag/dev/
mnt/mag/dev/nst29m
mnt/mag/dev/ttyS6
mnt/mag/dev/tty2
mnt/mag/dev/ipmo
mnt/mag/dev/port
mnt/mag/dev/ttyI8
mnt/mag/dev/sddh14
mnt/mag/dev/pppox44
mnt/mag/dev/ptyc3
mnt/mag/dev/ttyye
mnt/mag/dev/ttySR261
mnt/mag/dev/mga_vid
mnt/mag/dev/nvidia142

Весь печатать смысла нет сюда, первых 15 строк, думаю, достаточно чтобы все поняли о каком содержимом архива речь.

Задача получить из содержимого архива путь, куда была установлена система, какой каталог использовался для chroot, в выводе выше это /mnt/mag, но мог быть и другой, хоть /mnt/chroot, хоть /mnt/dir/dir/dir/dir/chroot. В общем-то, кто знает =)

Я привык, что в python'е используя регулярки, я могу указать скобками какую часть найденного мне надо сохранить и знаком ? могу из жадных делать ленивые квантификаторы.
С grep'ом что-то не прокатывает. Справку прочитал, ответ не нашел. Пробовал как -E, так и другие типы регулярок.
[console][xxblx@localhost mageia-chroot]$ tar -tf Mageia4_i586.tar.gz | grep -m 1 -o -E "^(.+?)/usr"
mnt/mag/usr[/console]
А надо чтобы в выводе было mnt/mag/ или mnt/mag

Пока что в голову пришло только
[console][xxblx@localhost mageia-chroot]$ tar -tf Mageia4_i586.tar.gz | grep -m 1 -o -E "^(.+?)/usr" | grep -o -E "^.+/"
mnt/mag/[/console]
Но это выглядит откровенно стремно.

Можно это как-нибудь более изящно сделать?

12.11.2014 19:41 · отредактировано #400664

Стоило только создать топик (а ведь и справку читал, и гуглил перед созданием), как тут же нагуглил похожий вопрос :D Ну и под свою задачу подправил
[console][xxblx@localhost mageia-chroot]$ tar -tf Mageia4_i586.tar.gz | grep -m 1 -o -P ".*(?=/usr/share/)"
mnt/mag[/console]

Но я все равно буду рад и другим вариантам, может без -P удастся обойтись. Оно мне не мешает никак, но мало ли.

13.11.2014 11:15 #400701

"xxblx" написал:
в выводе выше это /mnt/mag
дык в первой строке вывода tar это и написано.

ну вот так:
[console]$ echo "mnt/mag/
mnt/mag/usr/
mnt/mag/usr/share/" | sed -rn 's~(.*)/usr/~/\1~;T;p;q'
/mnt/mag
[/console]
13.11.2014 17:19 · отредактировано #400739
"drBatty" написал:
xxblx пишет:

в выводе выше это /mnt/mag

дык в первой строке вывода tar это и написано.

таки да чем не вариант оттуда брать?

Вариант через cut:

[console]echo "mnt/mag/usr/share/" | cut -f1,2 -d/[/console]

13.11.2014 17:33 #400740

А вот так как раз и можно узнать по первой строке в архиве:

[console]tar -tf 'our_archive.tar.gz' | sed -n '1p' [/console]

13.11.2014 17:54 · отредактировано #400743
"drBatty" написал:
дык в первой строке вывода tar это и написано.
"beliy" написал:
таки да чем не вариант оттуда брать?

Да, что-то я сглупил. Можно было просто grep'ом или sed'ом брать только 1-ую строку.

"beliy" написал:
Вариант через cut:

Этот вариант хорош, если /mnt/mag
Т.е. 2 каталога после корня.
А если будет /mnt/chroots/mageia/и_тут_уже_система, то вариант с cut извлечет все равно только первые два каталога после корня, т.е. /mnt/chroots, а значит путь будет получен неверный.

Но все равно спасибо, я на самом деле думал и сам на счет cut, но пришел к выводу, что такой вариант не универсален.
А вот grep и sed - оптимально, извлекают верный каталог вне зависимости от того насколько глубоко после корня он находится.

14.11.2014 05:10 #400789
"xxblx" написал:
Можно было просто grep'ом или sed'ом брать только 1-ую строку.

[console]$ head -n1[/console]

"xxblx" написал:
А вот grep и sed - оптимально, извлекают верный каталог вне зависимости от того насколько глубоко после корня он находится.
мой вариант с sed лучше:

1. выводит любой вариант, т.е. может удалять/добавлять что-то к выводу. Например слеш в начале.
2. в принципе быстрее, т.к. прерывается как только найдёт. (в данном случае sed прервётся, но tar всё равно будет читать до победного. Хотя его тоже можно и остановить маской файла, и вывести посл. строку командой tail -n1).
Войдите или зарегистрируйтесь, чтобы ответить.