6

文字列内のローマ数字をキャッチしたい (80 未満の数字で十分です)。有効なローマ数字のみを正規表現と一致させるにはどうすればよいですか?で良いベースを見つけました。. 問題は、文字列全体を扱うことです。文字列内のローマ数字を検出する方法はまだ見つかりませんでした。必須のものはなく、すべてのグループがオプションである可能性があるためです。これまでのところ、次のようなことを試しました:

my $x = ' some text I-LXIII iv more ';

if (  $x =~  s/\b(
                    (
                        (XC|XL|L?X{0,3}) # first group 10-90
                    |
                        (IX|IV|V?I{0,3}) # second group 1-9
                    )+
            )
        \b/>$1</xgi ) { # mark every occurrence
    say $x;
}

__END__
 ><some>< ><text>< ><>I<><-><>LXIII<>< ><>iv<>< ><more>< 
 desired output:
  some text >I<->LXIII< >iv< more 

したがって、すべてのグループがオプションであるため、これも単語境界をそれ自体でキャプチャします。それを成し遂げる方法は?どちらが必須かを判断できないときに、これらの 2 つのグループのいずれかを必須にする方法は? ローマ人を捕まえるための他のアプローチも大歓迎です。

4

2 に答える 2

4

Roman CPANモジュールを使用できます

use Roman;

my $x = ' some text I-LXIII VII XCVI IIIXII iv more ';
if (  $x =~  
    s/\b
    (
        [IVXLC]+
    )
    \b
    /isroman($1) ? ">$1<" : $1/exgi ) {
    say $x;
}

出力:

some text >I<->LXIII< >VII< >XCVI< IIIXII >iv< more 
于 2012-10-18T09:41:38.107 に答える
2

これは、Perlが他の場所で利用できる欠落している\<\>単語の始まりと終わりの境界)構造で私たちを失望させるところです。のようなパターンは、ターゲット文字列をまったく消費しない\b...\b場合でも一致します。これは、2番目の文字列が最初の単語の境界と2回目に一致するためです。...\b

ただし、エンドワードの境界は(?<=\w)(?!\w)、代わりにこれを使用できるようにするためのものです。

このプログラムはあなたが望むことをします。単語の境界で囲まれた潜在的なローマ字の文字列を先読みし(したがって、最初の単語の境界にいる必要があります)、その後に単語の文字が続かない有効なローマ数字をチェックします(つまり、単語の終わりの境界で再)。

>...<彼らが私を混乱させていたので、私はあなたのマークを逆にしたことに注意してください。

use strict;
use warnings;

use feature 'say';

my $x = ' some text I-LXIII iv more ';

if ( $x =~ s{
    (?= \b [CLXVI]+ \b )
    (
      (?:XC|XL|L?X{0,3})?
      (?:IX|IV|V?I{0,3})?
    )
    (?!\w)
    }
    {<$1>}xgi ) {

    say $x;
}

出力

some text <I>-<LXIII> <iv> more 
于 2012-10-18T11:53:32.650 に答える