2

SMAPI文法をJSGFに変換しています。これらは、さまざまな音声認識システムで使用される非常によく似た文法です。SMAPI は、他の世界と同じように疑問符を使用して、前のものの 0 または 1 を意味します。JSGF はこれに角括弧を使用します。stuff?そのため、文字列を のように変換し[stuff]、かっこで囲まれた文字列を のよう((((stuff)? that)? I)? like)?に変換する必要があります[[[[stuff] that] I] like]。のような文字列をそのままにしておく必要があります((((stuff) that) I) hate)。Qtax が指摘したように、より複雑な例は(foo ((bar)? (baz))?)に置き換えられ(foo [[bar] (baz)])ます。

このため、括弧で囲まれた式のすべてのレベルを抽出し、それが疑問符で終わっているかどうかを確認し、そうであれば括弧と疑問符を角括弧に置き換える必要があります。この質問に対する Eric Strom の回答は、ほぼ私が必要としているものだと思います。問題は、それを使用すると、一致した最大のグループ化が返されるのに対し、個々のグループ化ごとに操作を行う必要があることです。

これは私がこれまでに持っているものです: s/( \( (?: [^()?]* | (?0) )* \) ) \?/[$1]/xg. ((((stuff)? that)? I)? like)?ただし、 と一致すると、 のみが生成され[((((stuff)? that)? I)? like)]ます。これを行う方法についてのアイデアはありますか?

4

3 に答える 3

4

また、その質問に対する ysth の解決策を見て、この問題を解決するために既に利用可能なツールを使用することもできます。

use Text::Balanced qw(extract_bracketed);
$text = '((((stuff)? that)? I)? like)?';

for ($i=0; $i<length($text); $i++) {
    ($match,$remainder) = extract_bracketed( substr($text,$i), '()' );
    if ($match && $remainder =~ /^\?/) {
        substr($text,$i) =
            '[' . substr($match,1,-1) . ']' . substr($remainder,1);
        $i=-1; # fixed
    }
}
于 2012-06-25T17:29:19.577 に答える
2

古いバージョンの Perl (5.10 より前) では、これにコード アサーションと動的正規表現を使用できました。

 ...
 my $s = '((((stuff)? that)? I)? like)?';

 # recursive dynamic regex, we need
 # to pre-declare lexical variables
 my $rg;

 # use a dynamically generated regex (??{..})
 # and a code assertion (?{..})
 $rg = qr{
          (?:                       # start expression
           (?> [^)(]+)              # (a) we don't see any (..) => atomic!
            |                       # OR 
           (                        # (b) start capturing group for level
            \( (??{$rg}) \) \?      # oops, we found parentheses \(,\) w/sth 
           )                        # in between and the \? at the end
           (?{ print "[ $^N ]\n" }) # if we got here, print the captured text $^N
          )*                        # done, repeat expression if possible
         }xs;

 $s =~ /$rg/;
 ...

一致中、コード アサーションは次のすべての一致を出力します。

 [ (stuff)? ]
 [ ((stuff)? that)? ]
 [ (((stuff)? that)? I)? ]
 [ ((((stuff)? that)? I)? like)? ]

要件に応じてこれを使用するには、コード アサーションをわずかに変更し、キャプチャ用の括弧を適切な場所に配置して、一致を配列に保存します。

 ...
 my @result;
 my $rg;
 $rg = qr{
          (?:                      
           (?> [^)(]+)             
            |                      
            \( ( (??{$rg}) ) \) \?  (?{ push @result, $^N })
          )*                     
         }xs;

 $s =~ /$rg/ && print map "[$_]\n", @result;
 ...

それは言う:

 [stuff]
 [(stuff)? that]
 [((stuff)? that)? I]
 [(((stuff)? that)? I)? like]

よろしく

rbo

于 2012-06-25T18:23:15.263 に答える
1

いくつかの方法で解決できます。最も簡単なのは、置換が行われなくなるまで式を実行することです。例えば:

1 while s/( \( (?: [^()?]* | (?0) )* \) ) \?/[$1]/xg;

しかし、それは非常に非効率的です (深くネストされた文字列の場合)。

代わりに、次のように 1 回のパスで実行できます。

s{
  (?(DEFINE)
    (?<r>   \( (?: [^()]++ | (?&r) )*+ \)   )
  )

  ( \( )
  (?=   (?: [^()]++ | (?&r) )*+ \) \?   )

  |

  \) \?
}{
  $2? '[': ']'
}gex;
于 2012-06-25T17:18:03.327 に答える