Arhn - архитектура программирования

Как маркировать слово с помощью токенов, которые не полностью включены в слово?

Я понимаю, как использовать регулярное выражение в Perl следующим образом:

$str =~ s/expression/replacement/g;

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

$str =~ s/(a)/($1)dosomething/;

Но есть ли способ зафиксировать ($1) над за пределами выражения регулярного выражения?

У меня есть полное слово, которое представляет собой строку согласных, например. bEdmA, его гласная версия baEodamaA (где a и o — гласные), а также его разделенная форма из двух токенов, разделенных пробелом, bEd maA. Я хочу просто подобрать огласовку токенов из полного слова, например: beEoda, maA. Я пытаюсь захватить токен в полном выражении слова, поэтому у меня есть:

$unvowelizedword = "bEdmA";
$tokens[0] = "bEd", $tokens[1] = "mA";
$vowelizedword = "baEodamA";

foreach $t(@tokens) {
    #find the token within the full word, and capture its vowels
}

Я пытаюсь сделать что-то вроде этого:

$vowelizedword = m/($t)/;

Это совершенно неправильно по двум причинам: токен $t не присутствует в точно такой же форме, как bEd, но что-то вроде m/b.E.d/ было бы более уместным. Кроме того, как мне зафиксировать его в переменной вне регулярного выражения?

Реальный вопрос: как я могу зафиксировать огласованные последовательности baEoda и maA, учитывая токены bEd, mA из полного слова beEodamaA?


Редактировать

Из всех ответов я понял, что упустил две важные детали.

  1. Гласные необязательны. Итак, если токены: «Al» и «ywm», а полностью огласованное слово — «Alyawmi», то выходные токены будут «Al» и «yawmi».
  2. Я упомянул только две гласные, но их больше, включая символы, состоящие из двух символов, например «~a». Полный список (хотя я не думаю, что мне нужно упоминать его здесь):

    @vowels = ('a', 'i', 'u', 'o', '~', '~a', '~i', '~u', 'N', 'F', 'K' , '~N', '~К');

14.12.2011

  • Это не английский. Это транслитерация — эти символы обозначают гласные в другом языке. 15.12.2011

Ответы:


1

Следующее, похоже, делает то, что вы хотите:

#!/usr/bin/env perl
use warnings;
use strict;

my @tokens = ('bEd', 'mA');
my $vowelizedword = "beEodamaA";

my @regex = map { join('.?', split //) . '.?' } @tokens;

my $regex = join('|', @regex);
$regex = qr/($regex)/;

while (my ($matched) = $vowelizedword =~ $regex) {
    $vowelizedword =~ s{$regex}{};
    print "matched $matched\n";
}

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

#!/usr/bin/env perl
use warnings;
use strict;

my @tokens = ('bEd', 'mA', 'Al', 'ywm');
my $vowelizedword = "beEodamaA Alyawmi"; # Caveat: Without the space it won't work.

my @regex = map { join('.?', split //) . '.?$' } @tokens;

my $regex = join('|', @regex);
$regex = qr/($regex)/;

while (my ($matched) = $vowelizedword =~ $regex) {
        $vowelizedword =~ s{$regex}{};
            print "matched $matched\n";
}
14.12.2011
  • спасибо, это выглядит аккуратно и отлично работает - за исключением одного - гласные необязательны - я только что отредактировал вопрос. 14.12.2011
  • Заменить '.?' регулярное выражение с '(' . join('|', @vowels) . ')?' и вы можете приблизиться к тому, что вы хотите. 15.12.2011

  • 2

    Используйте оператор m// в так называемом «контексте списка», например:

    my @tokens = ($input =~ m/capturing_regex_here/modifiershere);

    14.12.2011

    3

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

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

    use strict;
    use warnings;
    use Data::Dumper;
    
    my @tokens = ("bEd", "mA");
    my $full = "baEodamA";
    
    my $vowels = "[aeiouy]";
    my @matches;
    for my $rx (@tokens) {
        $rx =~ s/.\K/$vowels?/g;
        if ($full =~ /$rx/) {
            push @matches, $full =~ /$rx/g;
        }
    }
    
    print Dumper \@matches;
    

    Вывод:

    $VAR1 = [
              'baEoda',
              'mA'
            ];
    

    Обратите внимание, что

    ... $full =~ /$rx/g;
    

    не требует захвата групп в регулярном выражении.

    14.12.2011
  • @briandfoy Это очень удобная функция, и она гораздо приятнее для глаз, чем другие варианты. 14.12.2011
  • Да все верно! гласные необязательны. Но как мне быть с тем фактом, что гласных может быть больше, чем один символ? Я только что отредактировал вопрос. 14.12.2011

  • 4

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

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

    Чтобы сопоставить токены, я могу использовать привязку \G с глобальным флагом /g в скалярном контексте. Это привязывает совпадение к символу на единицу после окончания последнего совпадения для того же скаляра. Этот способ позволяет мне иметь отдельные шаблоны для каждого суб-токена. Это намного проще в управлении, так как мне нужно только изменить список значений в @subtokens.

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

    use v5.14;
    
    my $vowels    = '[ao]*';
    my @subtokens = qw(bEd mA);
    
    # prepare the subtoken regular expressions
    my @patterns = map {
        my $s = join "$vowels", map quotemeta, (split( // ), '');
        qr/$s/;
        } @subtokens;
    
    my @tokens = qw( baEodamA mAabaEod baEoda mAbaEoda );
    
    my @grand_matches;
    TOKEN: foreach my $token ( @tokens ) {
        say "-------\nMatching $token..........";
        my @matches;
        PATTERN: foreach my $pattern ( @patterns ) {
            say "Position is ", pos($token) // 0;
    
            # scalar context /g and \G
            next TOKEN unless $token =~ /\G($pattern)/g; 
            push @matches, $1;
            say "Matched with $pattern";
            }
        push @grand_matches, [ $token, \@matches ];
        }
    
    # Now report the original   
    foreach my $tuple ( @grand_matches ) {
        say "$tuple->[0] has both fragments: @{$tuple->[1]}";
        }
    

    Теперь, вот хорошая вещь об этой структуре. Я, вероятно, неправильно угадал о вашей задаче. Если у меня есть, это легко исправить, не меняя настройки. Допустим, субтокены не обязательно должны быть в порядке. Это простое изменение шаблона, который я создал. Я просто избавился от якоря \G и флага /g;

            next TOKEN unless $token =~ /($pattern)/; 
    

    Или предположим, что жетоны должны быть в порядке, но между ними могут быть другие вещи. Я могу вставить .*?, чтобы соответствовать этому материалу, эффективно пропуская его:

            next TOKEN unless $token =~ /\G.*?($pattern)/g; 
    

    Было бы намного лучше, если бы я мог управлять всем этим из map, где я создаю шаблоны, но флаг /g не является флагом шаблона. Это должно быть связано с оператором.

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

    14.12.2011

    5

    Предполагая, что токены должны отображаться по порядку и без чего-либо (кроме гласной) между ними:

    my @tokens = ( "bEd", "mA" );
    my $vowelizedword = "baEodamaA";
    
    my $vowels = '[ao]';
    my (@vowelized_sequences) = $vowelizedword =~ ( '^' . join( '', map "(" . join( $vowels, split( //, $_ ) ) . "(?:$vowels)?)", @tokens ) . '\\z' );
    print for @vowelized_sequences;
    
    14.12.2011
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..