Регулярные выражения в shell(bash), на примере использования sed.

0
ГОТОВО: Ваш голос учтен!

Модификаторы повторения и жадность


Предположим, у нас есть отрывок HTML документа, со строки 2963 и до конца:


$ sed '2963,$! d' ../topic.html
<! -- Copyright Information -->
<div align='center' class='copyright'>
<a href='http://www.ibresource.ru/' style='text-decoration:none' target='_blank'>Форум</a> <a href='http://www.invisionboard.com' style='text-decoration:none' target='_blank'>IP.Board</a>
&copy; 2009 &nbsp;<a href='http://www.invisionpower.com' style='text-decoration:none' target='_blank'>IPS, Inc</a>.
<div>Лицензия зарегистрирована на: eMule-Rus.Net</div></div>
<! -- / Copyright -->
</td>
<td class="tableright1">&nbsp;</td>
</tr>
<tr>
<td colspan="3">
<table width="930" border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="tablebotleft1">&nbsp;</td>
<td class="tablebottomer1"><div style="text-align:right" class="edit">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://ipbskins.ru/" title="IPB Skins Team"><img src='style_images/retro/fis.gif' border='0' alt='IPB Skins Team, стиль Retro'></a>&nbsp;&nbsp;</div>
</td>
<td class="tablebotright1">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</body>
</html>

Читать такое интересно, но только в том случае, если вы изучаете HTML, если вам нужен текст, то теги лучше всего удалить. Теги в HTML всегда заключаются в <>, потому проще всего удалить всё между < и >


ищем не менее одного любого символа между <> и удаляем:


$ sed '2963,$! d' ../topic.html | sed -r 's/<.+>/ /g'




&copy; 2009 &nbsp; .




















Вот. почти ничего и нет. только это не так...


уже в 3й строке мы видим:


<a href='http://www.ibresource.ru/' style='text-decoration:none' target='_blank'>

Форум

</a> <a href='http://www.invisionboard.com' style='text-decoration:none' target='_blank'>

IP.Board

</a>


Выделены слова, которые почему-то удалились... Причина проста - точка в выражении <.+> означает

любой символ

, в том числе и >, потому в нашем случае:


< > < > < > < >


возможны варианты. Команда sed

жадная

, и захватывает всё что может, в данном случае всё между выделенных <>


<

> < > < > <

>

Вся нужная информация так-же оказывается удалённой

Crying or Very sad

В регулярных выражениях sed нельзя менять жадность(если бы было можно, то во первых нужно было решить вопрос с двусмысленными выражениями, а вовторых, sed пришлось бы просматривать строку несколько раз, что катастрофически убило бы скорость). В нашем случае всё просто - достаточно поменять точку(

любой символ

), на символьный класс [^>], означающий

любой, кроме >

.


$ sed '2963,$! d' ../topic.html | sed -r 's/<[^>]+>/ /g'



Форум IP.Board
&copy; 2009 &nbsp; IPS, Inc .
Лицензия зарегистрирована на: eMule-Rus.Net


&nbsp;





&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;

&nbsp;







После чего, неплохо будет заменить &nbsp; на пробел(это и есть пробел, только неразрывный), и кроме того, заменить все последовательности пробелов, на один пробел. Последнее делается командой s/ +/ /g, которая ищет последовательности из любого количества пробелов, и меняет их на 1 пробел. Ну и ещё надо учесть, что в тексте могут встретится табуляции, которые тоже кажутся многими пробелами, потому мы будем искать символ \s, который совпадает с любым пробельным символом:


$ sed '2963,$! d' ../topic.html | sed -r 's/<[^>]+>/ /g; s/&nbsp;/ /g; s/\s+/ /g'



Форум IP.Board
&copy; 2009 IPS, Inc .
Лицензия зарегистрирована на: eMule-Rus.Net



















Ну и неплохо будет удалить пустые строки, они совпадают с шаблоном /^ $/


$ sed '2963,$! d' ../topic.html | sed -r 's/<[^>]+>/ /g; s/&nbsp;/ /g; s/\s+/ /g'| sed '/^ $/d'
Форум IP.Board
&copy; 2009 IPS, Inc .
Лицензия зарегистрирована на: eMule-Rus.Net


Я использовал отдельную команду sed, что-бы было проще. Шаблон /^$/, которым обычно пользуются для поиска пустых строк, нам не подходит - в пустой строке может остаться 1 пробел(но только 1, потому /^ $/, а не /^ +$/)


Пожалуйста войдите, что-бы оставить коментарий.
Нет акаунта? Регистрация