LINUX.ORG.RU
ФорумAdmin

Регулярки в bash скриптах


0

2

Устал воевать... С ходу вопрос: каким образом в bash можно использовать полноценные PCRE выражения? Как я понял, в основном, используются POSIX. В последних нежадной квантификации не предусмотрено, вроде?

Задача:

Есть строка вида 'hostname-20130117-1' или 'hostname-20130117-i22.tar.gz'

Нужно регулярками выдрать из нее имя хоста/дату/счетчик и закинуть их в переменные. Ну или хотя бы счетчик, на худой конец.

С синтаксисом POSIX не знаком, с утилитами обработки строк тоже сейчас весело порезвился. Пробовал и так, и сяк, и sed, и expr - метод тыка не помог... =(

Скиньте рабочий пример, пожалуйста. ОС: Debian Squeeze.

Спасибо!


man cut

$ echo 'hostname-20130117-i22.tar.gz' | cut -d'-' -f 1
hostname

$ echo 'hostname-20130117-i22.tar.gz' | cut -d'-' -f 2
20130117

Со счётчиком немного посложнее, но не сильно. Например:

$ echo 'hostname-20130117-i22.tar.gz' | sed -e 's/^.*-//; s/\..*$//'
i22
akk ★★★★★
()
Последнее исправление: akk (всего исправлений: 1)

> Нужно регулярками выдрать из нее имя хоста/дату/счетчик и закинуть их в переменные.

регулярками? о_О

> Ну или хотя бы счетчик, на худой конец.

COUNTER=`basename host-name-20130117-i22.tar.gz .tar.gz | rev | cut -d- -f1 | rev`
arsi ★★★★★
()
Ответ на: комментарий от arsi

регулярками? о_О

Да я стандартные утилиты еще слабовато знаю. Может, можно и не регулярками, конечно.

Просто попробовал наиболее очевидное для меня решение и столкнулся с кучами непонятного. Вот пример:

#!/bin/sh

DIR="*/"
RES=$( ls -1dv $DIR | tail -1 )

echo source string:
echo $RES
echo

# PATT="'\(debsrv\)'"
# echo $PATT
# echo

echo replacement results:
echo "$RES" | sed -e 's/[0-9]*//'
echo 'hostname-20130117-i22.tar.gz' | sed -e 's/^.*-//; s/\..*$//'
source string:
debsrv-20130117-11/

replacement results:
debsrv-20130117-11/
i22

Первый sed с простейшей регой не сработал. Почему?! Непонятно...

Кстати, ключ -e (add the script to the commands to be executed) что дает в точности? К каким исполняемым командам он добавляется?..

Liber
() автор топика
Ответ на: комментарий от akk

akk, arsi, с cut'ом, вроде, немного разобрался:

#!/bin/sh

DIR="*/"
RES=$( ls -1dv $DIR | tail -1 )

echo source string:
echo $RES
echo

echo replacement results:
echo "$RES" | sed 's/\///; s/\..*$//' | cut --delimiter=- --fields=1,2,3,4 --output-delimiter="     "
source string:
debsrv-20130117-22-i.tar.gz/

replacement results:
debsrv     20130117     22     i

Спасибо!

А что не так с командой sed 's/[0-9]*//'?

Liber
() автор топика
Ответ на: комментарий от Liber

Кстати, вроде '-' - допустимый символ для имени хоста? Может лучше при именовании архивов использовать пробел в качестве разделителя?

Liber
() автор топика
Ответ на: комментарий от Liber

хотя наверное лучше при генерации имени архива в имени хоста делать замену - на _

Liber
() автор топика
Ответ на: комментарий от Liber

Кстати, вроде '-' - допустимый символ для имени хоста?

Допустимый. А '_' недопустимый.

akk ★★★★★
()

Можно так

#!/bin/bash
read Hostname Date Counter <<<"$( echo "hostname-20130117-i22.tar.gz" | awk '{ FS="[-.]"; $0=$0; printf("%s %s %s", $1, $2, $3); }' )"
echo "Hostname=$Hostname Date=$Date Counter=$Counter"
Результат
Hostname=hostname Date=20130117 Counter=i22

ATIpro ★★
()
Ответ на: комментарий от Liber

А что не так с командой sed 's/[0-9]*//'?

Это хороший вопрос.

$ echo "debsrv-20130117-11/" | sed -e 's/[0-9]*//'
debsrv-20130117-11/

$ echo "20130117-11/" | sed -e 's/[0-9]*//'
-11/

То есть если [0-9]* приходится не на начало строки, то замена не происходит. Интересно, почему?

akk ★★★★★
()
Последнее исправление: akk (всего исправлений: 1)
Ответ на: комментарий от ATIpro

ATIpro, спасибо за пример. Я awk мельком глянул, понял что тулза избыточно мощная и сложная для данного случая, поэтому не стал лезть в дебри.

Liber
() автор топика
Ответ на: комментарий от anonymous

pcregrep

Правильно ли я понимаю, что выдирать сабпаттерны он не умеет? Зачем он нужен тогда?

Да, какие отличия между grep -P и grep -E?

Tanger ★★★★★
()
Ответ на: комментарий от akk

То есть если [0-9]* приходится не на начало строки, то замена не происходит. Интересно, почему?

замените на sed -e 's/[0-9]\+//'

Sorcerer ★★★★★
()
Ответ на: комментарий от Sorcerer

Это понятно, что «один или более» должен сработать.

В общем, теперь понятно и про [0-9]*. Это «ноль или более». Вот он на ноле и заканчивает.

akk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.