Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Изобретаем велосипед


Автор: MakTpaxep 5.7.2011, 11:31
Всем привет.
Задача:
Код

<tag att="first">qwe<tag att="second">asd</tag>zxc</tag>

Заменить на:
Код

<first>qwe<second>asd</second>zxc</first>

В принципе, задача для какого-нибудь xml'ного модуля, но интересно можно ли сделать одним регом?

Автор: alezzz 5.7.2011, 11:45
Код

while ($a =~ s#<tag att="([^"]*)">((?:.(?!<tag))*?)</tag>#<$1>$2</$1>#) {};

Автор: afiskon 5.7.2011, 11:54
http://eax.me/regular-expr/

Автор: MakTpaxep 5.7.2011, 12:25
Цитата(afiskon @  5.7.2011,  11:54 Найти цитируемый пост)
учите. мат. часть.

Основы я и так знаю, хорош тут тиц качать) И я, кстати, тоже готов убивать за [a-z] и [0-9] вместо \w и \d =)



Цитата(alezzz @  5.7.2011,  11:45 Найти цитируемый пост)
while ($a =~ s#<tag att="([^"]*)">((?:.(?!<tag))*?)</tag>#<$1>$2</$1>#) {};

Спасибо=)

Автор: arto 5.7.2011, 12:42
# print '<tag att="first"><tag att="second">asd</tag>qwe<tag att="second">asd</tag>zxc</tag>' | perl -plne 'while (s#<tag att="([^"]*)">((?:.(?!<tag))*?)</tag>#<$1>$2</$1>#) {};'
<first><second>asd</first>qwe<second>asd</second>zxc</second>
# 


Автор: alezzz 5.7.2011, 12:43
Цитата(MakTpaxep @  5.7.2011,  12:25 Найти цитируемый пост)
И я, кстати, тоже готов убивать за [a-z] и [0-9] вместо \w и \d =)

почему?

Добавлено через 3 минуты и 25 секунд
arto, есть косяк.

(?:.(?!<tag))* -- вот эту часть не могу вспомнить как правильно сделать, у Фридла было как-то по другому.

Автор: afiskon 5.7.2011, 12:47
Цитата(alezzz @ 5.7.2011,  12:43)
Цитата(MakTpaxep @  5.7.2011,  12:25 Найти цитируемый пост)
И я, кстати, тоже готов убивать за [a-z] и [0-9] вместо \w и \d =)

почему?

Мне вот тоже интересно. Во-первых, [a-z0-9] не идентично \w. Во-вторых, \d в perl 5.14 и \d в perl < 5.14 работают по-разному, так что если нужен [0-9], лучше писать [0-9].

Автор: MakTpaxep 5.7.2011, 12:53
Цитата(arto @  5.7.2011,  12:42 Найти цитируемый пост)
# print '<tag att="first"><tag att="second">asd</tag>qwe<tag att="second">asd</tag>zxc</tag>' | perl -plne 'while (s#<tag att="([^"]*)">((?:.(?!<tag))*?)</tag>#<$1>$2</$1>#) {};'<first><second>asd</first>qwe<second>asd</second>zxc</second># 

Действительно. Как мы это будем решать?
Или даже так
Код

<tag att="first"><tag att="second">asd</tag>qwe<tag att="second">asd<tag att="third">qwe</tag>asd</tag>zxc</tag>

У меня вроде появились мысли с использованием рекурсии и модификатором e.
Попробую сейчас оформить)

Цитата(alezzz @  5.7.2011,  12:43 Найти цитируемый пост)
почему?

Чтобы не раздувать код. Ещё когда utf8 входные - [a-z] не опишут всех букв) А [0-9] вроде эквивалентно \d, разве нет?

Автор: alezzz 5.7.2011, 13:07
Вот, кажется так точнее будет:
Код

while ($a =~ s#<tag att="([^"]*)">((?:(?!<tag).)*?)</tag>#<$1>$2</$1>#) {};

Автор: arto 5.7.2011, 13:12
неужели сложно проверить?

# print '<tag att="first"><tag att="second">second 1</tag>first 1<tag att="second">second 2</tag>first 2</tag>' | perl -0777 -plne 's#<tag att="([^"]*)">((?:(?!<tag).)*?)</tag>#<$1>$2</$1>#gsm' 
<tag att="first"><second>second 1</second>first 1<second>second 2</second>first 2</tag>
#

Автор: alezzz 5.7.2011, 13:15
и в каком месте ошибка?

Код

$a = '<tag att="first"><tag att="second">second 1</tag>first 1<tag att="second">second 2</tag>first 2</tag>';

while ($a =~ s#<tag att="([^"]*)">((?:(?!<tag).)*?)</tag>#<$1>$2</$1>#) {};
print $a;


Цитата

<first><second>second 1</second>first 1<second>second 2</second>first 2</first>


Добавлено через 2 минуты и 16 секунд
я не через /g делал, а в цикле

Автор: MakTpaxep 5.7.2011, 14:34
alezzz, спасибо. 

Автор: MakTpaxep 2.11.2011, 19:00
Код

    $_="<qwe att=2>aaaaa<qwe att=1>bbbbbbbbb</qwe>cccccc</qwe>";
    my $lev;
    $lev=qr(<qwe att=([^>]+)>((?:(?:(?!<qwe).)|$lev)+)</qwe>);
    s!$lev!<$1>$2</$1>!g;

Итого "<qwe att=2>aaaaa<1>bbbbbbbbb</qwe>cccccc</1>".
Почему не получается?

Пардон:
Код

$lev=qr(<qwe att=([^>]+)>((?:(?:(?!<qwe).)|(??{$lev}))+)</qwe>);

но тогда выходит
Код

<2>aaaaa<qwe att=1>bbbbbbbbb</qwe>cccccc</2>

Без while не обойтись видимо...

Автор: alezzz 2.11.2011, 19:24
без while этим способом не получится, модификатором global можно только ускорить

Автор: tishaishii 4.11.2011, 21:51
Код
perl -MXML::LibXSLT

XML::LibXSLT->new->parse_stylesheet(XML::LibXML->load_xml(IO=>\*DATA))->transform(XML::LibXML->load_xml(IO=>\*STDIN))->toFH(\*STDOUT)

__DATA__
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="tag">
        <xsl:element name="{@att}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="*">
        <xsl:value-of select="."/>
    </xsl:template>
</xsl:stylesheet>

Автор: tishaishii 5.11.2011, 00:35
Код
perl -p

s{
    (<)
    (?:
        ([\w\-\:]+)\s+att=(["'])(.*?)\3\s*(/)?    |
        /([\w\-\:]+)
    )
    (>)
}{
    if(length $6) {
        if('ARRAY' eq ref $tags{$6} && @{$tags{$6}}) {
            +"$1/".pop(@{$tags{$6}}).$7
        } else {
            die 'Несбалансированный набор'
        }
    } elsif(length $5) {
        +"$1$4/$7"
    } else {
        push @{$tags{$2}||=[]}, $4;
        +"$1$4$7"
    }
}igogosex

Автор: MakTpaxep 7.11.2011, 13:32
tishaishii, спасибо, раскурю на досуге)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)