展開された正規表現を展開されていない形式で印刷するにはどうすればよいですか?


8

拡張表記(qr/.../x)を使用して作成された正規表現を非拡張形式で印刷することはできますか?例えば:

my $decimal = qr/
  (?=\d|\.\d)  # look-ahead to ensure at least one of the optional parts matches
  \d*          # optional whole digits
  (?:\.\d*)?   # optional decimal point and fractional digits
/x;

say $decimal;

これをとして印刷してほしい(?=\d|\.\d)\d*(?:\.\d*)?

機能しない部分を取り除くパーサーを作成することもできますが、これはperlがすでに行っていることを複製することになるため、重要なケースのいくつかが間違っている可能性があります。

(はい、これは少しばかげているようです。多くのメッセージを印刷する必要がありmatched <pattern>、パターンに拡張表記を使用できるようにしながら、メッセージを1行に制限したいというユースケースがあります。)


コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
Samuel Liew

回答:


7

Perlはそのようなユーティリティを提供していません。正規表現パターンを解析します。それらは生成されません。オブジェクトの文字列化は、パーサーに提供される正確な文字列(?:...)であり、フラグを説明するにラップされます。パーサーに提供される文字列は、補間後のリテラルから区切り文字を引いたものです。[1]

とは言っても、これは正規表現パーサーで行うのは簡単です。

YAPE :: Regexがありますが、長い間更新されていません。たとえば(?^:...)、Perlの最新バージョンの正規表現の文字列化で見つかったはサポートされていません。

Regexp :: Parserもあります。新しいですが、(?^:...)どちらもサポートしていません!しかし、それを回避するのであれば、空白やコメントは自然に無視されるので完璧です!パターンを解析し、解析ツリーから文字列を取得するだけです。

最後に、あります正規表現:: Parsertronが。これは最新で、をサポート(?^:...)していますが、空白とコメントを「完全一致」トークンと区別していません。

Regexp :: Parserを使用しましょう。[2]

#!/usr/bin/perl
use strict;
use warnings;
use feature qw( say );

use Regexp::Parser qw( );

{
   @ARGV == 1
      or die("usage\n");

   my $re = $ARGV[0];

   # R::P doesn't support «(?^:...)», so we'll
   # provide a backwards-compatible stringification.
   $re =~ s{^\(\?\^(\w*):}{
      my %on = map { $_ => 1 } split //, $1;
      my $on  = join "", grep  $on{$_}, qw( i m s x );
      my $off = join "", grep !$on{$_}, qw( i m s x );
      "(?$on-$off:"
   }e;

   my $parser = Regexp::Parser->new($re);
   my $roots = $parser->root
      or die($parser->errmsg);

   say join "", map $_->visual, @$roots;
}

テスト:

$ despace_re '(?^x:
   (?=\d|\.\d)  # look-ahead to ensure at least one of the optional parts matches
   \d*          # optional whole digits
   (?:\.\d*)?   # optional decimal point and fractional digits
)'
(?x-ims:(?=\d|\.\d)\d*(?:\.\d*)?)

  1. \Q\uおよび同様の処理が補間の同じ段階で行われます。現在の文字名設定を不滅にするために\N{...}解決さ\N{U+...}れます。、、およびなどの他のエスケープ\x27\x{0000027}、文字ごとに保持されます。\\\/

  2. YAPE :: Regexに基づくソリューションは、この回答の以前のリビジョンで使用されていまし


1
で検索を追加しますre::regex_pattern($qr)か?おそらく、単純なサブで、彼らが必要なものを取得する方法、またはそれに近いを与えないこと
zdim

@zdim、どのようにre::regex_pattern($qr)役立つかはわかりません。
池上

それは周囲のものを削除し(?: )ます()... それはなんかです。スペースは私が気づいている厄介ですx-modがある場合でも内部に正当なスペースが存在する可能性があります[ ](思い出すことができる1つの例、おそらくそれ以上あります)...しかし、手動で改行を取り除くことができますか?次に、許容できるプリントアウトがありますか?
zdim

@zdim、それを削除するのは悪いことです。それはパターンを変更して別のものを意味する可能性があります。それはパターンの重要な部分だからです。
池上

@zdim、使用している場合、空白が重要である四つの例/x\␠[␠](?-x:␠)(?-x)␠。もっとあるかもしれません。
池上
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.