LINUX.ORG.RU

Регулярные выражения в sed

 , ,


0

1

Добрый день. Встала тут такая задача: есть текстовик с относительными ссылками на файлы, расположенные на веб-сервере. Текстовик вида

<item id="blablabla" href="blablabla.html" media-type="blablabla"/>
<item id="blablabla2" href="directory/blablabla.html" media-type="blablabla"/>
надо превратить в формат «по ссылке на строку», чтобы потом его скормить wget-у. Как это сделать в текстовом редакторе через замену по регулярному выражению, либо средствами популярных языков вроде PHP, Java или даже Python — относительно понятно, однако мне бы хотелось оформить все это в виде скрипта. Я составил регулярку, однако совершенно не понял того, как вытащить значение второй по счету (.*)
/\<item id="(.*)" href="(.*)"(.*)>/g
Прошу помочь знающих людей

$ echo "<'one' 'two' 'three'>" | sed "s/<'\(.*\)' '\(.*\)' '\(.*\)'>/\1-\2-\3/g"
one-two-three
crutch_master ★★★★★
()

как вытащить значение второй по счету (.*)
/\<item id="(.*)" href="(.*)"(.*)>/g

sed 's/<item id="[^"]*" href="\([^"]*\)".*>/\1/' < tekstovik
pS
()
Ответ на: комментарий от kolyanok

sed 's/<item id=«[^»]*" href=«\([^»]*\)".*>/\1/' < tekstovik

таки да, если несколько ссылок в одной строке, то

sed 's/<item id="[^"]*" href="\([^"]*\)".*>/\1/g' < tekstovik
опцию g в конце регулярки надо добавить.

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

UPD: и ещё подрихтовать:

sed 's/<item id="[^"]*" href="\([^"]*\)"[^>]*>/\1\n/g' < tekstovik | grep -v \^\$
Можно (но, вроде, необязательно) убрать пробелы в начале строки, там, где <...> <...> разорвано пробелами.

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

Взгруснулось. Нате вам поуниверсальнее: можно писать на каждой строке или через пробельные символы на одной, после < можно пробелы, скипает если не Item, причём в любом регистре, HREF= может быть любым по счёту атрибутом. Кавычки любые, в том числе и без.

#!/bin/bash

while true; do
    IFS='>' read -r -a tags
    [ $? -ne 0 ] && break
    for tag in "${tags[@]}"; do
	IFS=$' \t\n' read -r -a items <<< "$tag"
	tag_name=
	uri=
	for i in "${items[@]}"; do
		echo "for($i)"
		tag=${i^^*}
		if [ -z "$tag_name" ]; then
			if [ "x<" = "x$tag" -o "<ITEM" = "$tag" ]; then
				tag_name=$tag
				continue
			else
				break
			fi
		fi
		if [ "x<" = "x$tag_name" ]; then
			if [ "ITEM" = "$tag" ]; then
				tag_name="<ITEM"
				continue
			else
				break
			fi
		fi

		if [ HREF= = "${tag:0:5}" ]; then
			IFS='=' read -r -a items <<< "$i"
			uri=${items[1]}
			break
		fi
	done
	[ -z "$uri" ] && continue
	i=${uri:0:1}
	if [ '"' = "$i" -o "'" = "$i" ]; then
		uri=${uri:1:${#uri}-2}
	fi
	echo "$uri"
    done
done

vodz ★★★★★
()

Судя по /> в конце тегов, у вас исходный документ со списком это валидный XML. Это значит можно воспользоваться более подходящими инструментами для работы со структурированным текстом. Например, XSL-шаблонами. Они, конечно, не так просты для изучения, как регулярки, и весьма многословны, но зато позволяют вертеть исходным документом, как вам только заблагорассудится.

$ cat list.xml 
<?xml version="1.0"?>
<list>
<item id="blablabla" href="blablabla.html" media-type="blablabla"/>
<item id="blablabla2" href="directory/blablabla.html" media-type="blablabla"/>
</list>
$ xsltproc - list.xml <<EOF
> <?xml version="1.0"?>
> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> <xsl:output method="text"/>
> <xsl:template match="//item">
> <xsl:value-of select="@href"/>
> <xsl:text>
> </xsl:text>
> </xsl:template>
> <xsl:template match="text()"/>
> </xsl:stylesheet>
> EOF
blablabla.html
directory/blablabla.html

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