Programmingフルスタック 開発者

Perlの正規表現における量指定子の遅延処理と貪欲処理の原則を説明してください。それが文字列の解析にどのように影響するかを示してください。微妙な点や非標準的な動作の例を示してください。

Hintsage AIアシスタントで面接を突破

回答。

Perlにおいて、正規表現の量指定子 *, +, ?, {n,m} はデフォルトで貪欲greedy)です:彼らは、パターンに一致する可能な限り多くの文字をキャプチャします。

量指定子の後に ? を追加すると、それは遅延lazyまたはnon-greedy)になり、一致する正規表現全体が合うために最小限の文字をキャプチャします。

貪欲な一致の例:

my $str = 'foo <bar> baz <quux>'; $str =~ /<.*>/; # '<bar> baz <quux>'をキャプチャします

遅延な一致の例:

my $str = 'foo <bar> baz <quux>'; $str =~ /<.*?>/; # '<bar>'をキャプチャします

特徴:

貪欲な表現は、HTMLや他の入れ子構造の解析時に予期しないほど多くを「食べる」ことがあります!


トリックのある質問。

<a><b><c> という文字列の解析において、次の二つの正規表現 /<(.*)>//<(.*?)>/ は何が違いますか?

回答:

  • /<(.*)>/ (貪欲)は最大のブロックをキャプチャします — 一致:<a><b><c>
  • /<(.*?)>/ (遅延)は最初のグループだけをキャプチャします:<a>

例:

my $s = '<a><b><c>'; $s =~ /<(.*)>/; # $1: 'a><b><c' $s =~ /<(.*?)>/; # $1: 'a'

このテーマの微妙さを知らなかったための実際のエラーの例。


物語

ニュース見出しをインポートするアプリケーションで、プログラマーは /\<(.*)\>/ を使用して <title>ニュース</title> のタグ名を解析しようとしました。その結果、正規表現は最初の < と最後の > の間の全ての文字列をキャプチャしましたが、必要な要素をキャプチャしませんでした。入れ子のタグが現れたときにエラーが見つかりました。


物語

論理パーサーにおいて、quoted stringsを抽出するために使用されたパターン /"(.*)"/ は予期せず最初と最後の引用符の間の全てをキャプチャしました。その結果、マークアップが正しく分解されず、パターンを /"(.*?)"/ に置き換えるまで問題が解決しませんでした。


物語

引用符を含むCSVの自動パーサーでは、「貪欲」に基づいたパターンが誤って書かれたため、複数の列が一つに結合されてしまいました。入力されたパーサーの拒否は大規模データでのみ明らかになり、パターンの遅延修正が問題を解決しました。