1

次の規則に従う必要がある文字列を検証するための正規表現を作成しました。

  1. 少なくとも 1 文字である必要があります
  2. 空白文字を含めることはできません
  3. 最初の文字は句読点であってはなりません
  4. 最後の文字は句読点であってはなりません
  5. 数字が続く句読点で終わることはできません
  6. 他のすべての文字は、. 以外の任意の UTF-8 文字にすることができます/[:@#]

正規表現は次のとおりです。

my $name_re = qr/
     [^[:punct:][:blank:]]      #  not punct or blank
     (?:                        #  followed by...
         [^[:blank:]:@#]*       #      any number non-blank, non-@, non-#, non-@
         [^[:punct:][:blank:]]  #      one not blank or punct
     )?                         #  ... optionally
/x;

足りないものがありますか?ルール 5 は適用されません。私はこのようなコードを書くことによってそれを強制してきました:

die "$proj is not a valid name" unless $proj =~ /\A$name_re\z/
    && $proj !~ /[[:punct:]][[:digit:]]+\z/;

これを行わなければならない場所がたくさんあるので、すべてを単一の正規表現で実行したいと思います。問題は次のとおりです。「foo,23」などの値を拒否する正規表現は?

4

2 に答える 2

3

以下が機能するはずです。

my $name_re = qr/
    \A(?![[:punct:]])         # first character isn't punctuation
    (?:                       # start non-capturing group, repeated once or more
       (?![[:punct:]][[:digit:]]+\z)  # make sure 5th condition isn't violated
       [^[:blank:]:@#]                # match a valid character
    )+                        # end non-capturing group
    (?<![[:punct:]])\z        # last character isn't punctuation
/x;

アンカーを正規表現内に移動したことに注意してください。これは、現在の方法では完全に必要ではないかもしれませんが、すべてを1か所にまとめた方が明確になると思います。

(?!...)(?<!...)は、それぞれ否定先読みと後読みです。これらは、このようなことを確認することを非常に簡単にします。基本的に、中間セクションは「これらの有効な文字に一致する」ことができ、最初と最後に先読み/後読みでそれらの条件を確認できます。

中間の否定先読みは、指定された位置で、句読点または数字だけでは文字列の末尾に一致できないことを検証します。つまり、条件 5 に違反していないことを確認します。この先読みは繰り返しグループ内にあるため、すべての位置でチェックされます。

可変長の後読みを使用できれば、これはより簡単になりますが、Perl はそれらをサポートしていないと思います。

于 2012-08-09T22:27:43.860 に答える
0

@fjの答えは、完全な文字列の一致には正しいですが、より大きな文字列の一部としてその中の他のものと一致できるバリアントも必要です。そのバージョンは次のとおりです。

my $name_re = qr/
    (?![[:punct:]])                # first character isn't punctuation
    (?:                            # start non-capturing group, repeated once or more ...
       (?!                         #    negative look ahead for...
           [[:punct:]]             #       punctuation
           [[:digit:]]+            #       digits
           (?:$|[[:blank:]])       #       eol or blank
       )                           #    ...
       [^[:blank:]:@#]             #     match a valid character
    )+                             # ... end non-capturing group
    (?<![[:punct:]])\b             # last character isn't punctuation
/x;
于 2012-08-17T05:19:39.080 に答える