LINUX.ORG.RU

[sed] Проблема при извлечении подстроки через regexp

 


0

0

Доброго времени суток! Есть строка вида: kljfhgdfjk ; lfjkghdjkfgh && klfh&kdfgh Пытаюсь sed-ом вытащить кусок строки идущий после последнего «&&» или ";" (смотря, что ближе к концу строки расположено). Делаю так:

echo 'kljfhgdfjk ; lfjkghdjkfgh && klfh&kdfgh' | sed -n 's/.*\(&&|;\)\ *\([^&{2},^;]*\)\ *$/\2/p'
Однако сия изящная конструкция ничего не возвращает. Даже ошибок. Пробовал последовательно упрощать регулярное выражение. Заработало следующее:
echo 'kljfhgdfjk ; lfjkghdjkfgh && klfh&kdfgh' | sed -n 's/.*&&\ *\([^&{2},^;]*\)/\1/p'
Возвращает, как и ожидается, «klfh&kdfgh», но в практических целях сия изящная конструкция непригодна, т.к. не охватывается вариант, когда после «&&» в строке есть ещё ";". Почему sed ничего не возвращает, если вместо «&&» в регулярном выражении поставить «\(&&|;\)» и заменять строку на вторую подгруппу вместо первой, неясно. Кроме того, непонятно, чем не нравится «\ *$», отсекающая пробелы в конце строки, в самом конце регулярного выражения. Что я делаю не так?

Ответ на: комментарий от akk

Любой символ, кроме двойного & и точки с запятой. Вообще, под группой «\([^&{2},^;]*\)» я подразумевал последовательность любой длины (вплоть до нулевой), состоящую из любых символов, кроме двойного & и точки с запятой.

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

Внутри [^] никакие {2} не работают. Это воспринимается как три символа: {, 2 и }. Вам надо что-то типа [^&]{2}

akk ★★★★★
()

Вероятно, тут лучше не пытаться всё впихнуть в один монстроидальный регэксп, а разбить на несколько более простых.

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

«\([^&{2},^;]*\)» работает, насколько я понимаю, правильно. По крайней мере, когда я начал упрощать первоначальный рэгэксп, я добился рабочего варианта без изменений этого куска. Проблемы возникают, если помимо вышеуказанной группы в рэгэксп добавить группу "(&&|;)", чтобы возвращалась часть строки, идущая после ";", если ";" окажется ближе к концу строки, чем «&&». Если в конец рэгэкспа после «\([^&{2},^;]*\)» добавить «\ *$», рэгэкпс тоже начинает работать не так, как надо.

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

«\([^&{2},^;]*\)» работает, насколько я понимаю, правильно.

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

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

Попробовал «\([^&{2},^;]*\)» заменить на «\(.*\)». Получилось следующее:

echo 'kljfhgdfjk ; lfjkghdjkfgh && klfh&kdfgh' | sed -n 's/.*&&\ *\(.*\)/\1/p'
Возвращает «klfh&kdfgh», как и ожидается.
echo 'kljfhgdfjk ; lfjkghdjkfgh && klfh&kdfgh' | sed -n 's/.*\(;|&&\)\ *\(.*\)/\2/p'
Не возвращает ничего, а ожидается, что вернёт снова «klfh&kdfgh».

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

PS

Для sed в «\(&&|;\)» ошибка, перед «|» нужен «\»

echo 'kljfhgdfjk ; lfjkghdjkfgh && klfh&kdfgh' | sed -n 's/^.*\(&&\|;\)//p'

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

Почитай info sed.

`REGEXP1\|REGEXP2'
     Matches either REGEXP1 or REGEXP2.  Use parentheses to use complex
     alternative regular expressions.  The matching process tries each
     alternative in turn, from left to right, and the first one that
     succeeds is used.  It is a GNU extension.

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

Спасибо. Теперь работает как надо. Кстати, раз уж коснулись этого момента, какой рэгэксп будет соответствовать строке без двойного «&» и ";", если «[^&{2},;]*» не катит?

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

Только такой способ могу предложить:

echo "kljfhgd \n fjk ; lfjkghd \n jkfgh && klfh&kdfgh" | sed -n '/&&\|;/! s/k/[K]/gp' 
[K]ljfhgd 

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