Почему это регулярное выражение не выполняется?

#regex #perl #markdown #foswiki

Вопрос:

Я пытаюсь преобразовать свою личную вики-страницу из Foswiki в файлы Markdown, а затем в развертывание JAMstack. Foswiki использует плоские файлы и хранит метаданные в следующем формате:

 %META:TOPICINFO{author="TeotiNathaniel" comment="reprev" date="1571215308" format="1.1" reprev="13" version="14"}%
 

Я хочу использовать репозиторий git для управления версиями и буду беспокоиться о том, чтобы связать это с метатадой статьи позже. На данный момент я просто хочу преобразовать эти блоки во что-то, что выглядит следующим образом:

 ---
author: Teoti Nathaniel
revdate: 1539108277
---
 

После небольшой настройки я построил следующее регулярное выражение:

 author=['"](\w )['"](?:.*)date=['"](\w )['"]
 

Согласно регулярному выражению 101, это работает, и мои две группы захвата содержат желаемые результаты. Попытка фактически запустить его:

 perl -0777 -pe 's/author=['"](\w )['"](?:.*)date=['"](\w )['"]/author: $1nrevdate: $2/gms' somefile.txt
 

дает мне только это:

 >
 

Моя предыдущая попытка (которая прерывается, если детали не расположены в определенном порядке) выглядела так и была выполнена правильно:

 perl -0777 -pe 's/%META:TOPICINFO{author="(.*)" date="(.*)" format="(.*)" (.*)}%/author:$1 nrevdate:$2/gms' somefile.txt
 

Я думаю, что это проблема с escape-персонажем, но не могу ее решить. Я даже пошел и нашел этот инструмент, чтобы убедиться, что они верны.

Грубое принуждение меня к пониманию здесь является одновременно неэффективным и разочаровывающим, поэтому я прошу сообщество о помощи.

Комментарии:

1. Совет: /m бесполезно, если вы не используете ^ или $

Ответ №1:

Первая серьезная проблема заключается в том, что вы пытаетесь использовать одинарную кавычку ( ' ) в программе, когда программа передается в оболочку в одинарных кавычках.

Экранируйте любой экземпляр ' в программе с помощью ''' . Вы также можете использовать x27 , если цитата представляет собой один строковый литерал в двойных кавычках или литерал регулярного выражения (как в случае каждого экземпляра в вашей программе).

 perl -0777pe's/author=['''"].../.../gs'
 
 perl -0777pe's/author=[x27"].../.../gs'
 

Ответ №2:

Я бы попытался разбить его на чистую структуру данных, а затем обработать. Разделив обработку данных на печать, вы можете изменить их, чтобы позже добавить дополнительные данные. Это также делает его гораздо более читабельным. Пожалуйста, посмотрите пример ниже

 #!/usr/bin/env perl
use strict;
use warnings;
## yaml to print the data, not required for operation
use YAML::XS qw(Dump);
my $yaml;

my @lines = '%META:TOPICINFO{author="TeotiNathaniel" comment="reprev" date="1571215308" format="1.1" reprev="13" version="14"}%';

for my $str (@lines )
{
    ### split line into component parts
    my ( $type , $subject , $data ) = $str =~ /%(.*?):(.*?){(.*)}%/;
    ## break data in {} into a hash
    my %info = map( split(/=/),  split(/s /, $data) );

    ## strip quotes if any exist
    s/^"(.*)"$/$1/ for values %info;

    #add to data structure
    $yaml->{$type}{$subject} = %info;
}
## yaml to print the data, not required for operation
print Dump($yaml);

## loop data and print
for my $t (keys %{ $yaml } ) {
    for my $s (keys %{ $yaml->{$t} } ) {
        print "-----------n";
        print "author: ".$yaml->{$t}{$s}{"author"}."n";
        print "date: ".$yaml->{$t}{$s}{"date"}."n";
    }
}
 

Ответ №3:

Хорошо, я продолжал дурачиться с этим, сократив выполнение до одного срока и расширив его. Я скоро добрался сюда:

 $ perl -0777 -pe 's/author=['"](\w )['"](?:.*)date=['"](\w )['"]/author: $1\nrevdate: $2/gms' somefile.txt

Unmatched [ in regex; marked by <-- HERE in m/author=["](w )["](?:.*)date=["](w )[ <-- HERE "]/ at -e line 1.
 

В конце концов это привело меня сюда:

 perl -0777 -pe 's/author=['"](\w )['"](?:.*)date=['"](\w )['"]/nauthor $1nrevdate:$2n/gms' somefile.txt
 

Что дает беспорядочный результат, но работает. (Примечание: Вывод является доказательством концепции, и теперь его можно использовать в скрипте Python для программной генерации метаданных уценки.

Спасибо, что был моим резиновым утенком, StackOverflow. Надеюсь, это кому-нибудь пригодится, где-нибудь, когда-нибудь.

Комментарии:

1. Заменить perl -0777 -pe на printf %s . Ваша программа не такая, как вы думаете. Вы передаете следующее perl : s/author=["](w )["](?:.*)date=["](w )["]/nauthor $1nrevdate:$2n/gms . Обратите внимание на отсутствие одинарных кавычек.