允许使用PosixPrint字符,%\ /#除外。 :以及字符串开头和结尾处的空格除外

时间:2019-04-10 14:41:38

标签: regex perl pcre

因此对于此Allow PosixPrint Characters except , % \ / # ? :条件有效

使用此正则表达式模式m/^[^\P{PosixPrint}\/\#\%\?\:\,\\]+$/x

但是为此:

white-space at the beginning and end but allow in the middle

此模式m/^\b[^\P{PosixPrint}\/\#\%\?\:\,\\]+\b$/x可以正常工作(请参见输出)。

如果[0-9a-zA-Z]以外的任何字符出现在开头和结尾,则该字符串不匹配。

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $vars = [
    q#1#,
    q#1~`!l#,
    q#11#,
    q#111#,
    q#1 1#,
    q# 11#,
    q#11 #,
    q# 11 #,
    q# 1 1 #,
    q#1`~!@$^&*()-_=+|]}[{;'".><1#,
    q#1`~!@$^&*()-_=1#,
    q#1~`!@$^&*()-_=+|]}[{;'".><#,
    q#~`!@$^&*()-_=+|]}[{;'".><1#,
    q#~`!@$^&*()-_=+|]}[{;'".><#,
];

foreach my $var (@$vars){
    if ( $var =~ m/^\b[^\P{PosixPrint}\/\#\%\?\:\,\\]+\b$/x) {
        print "match:\t\t#$var#\n";
    }
    else{
        print "no match:\t#$var#\n";
    }
}

输出:

    match:      #1#
    match:      #1~`!l#
    match:      #11#
    match:      #111#
    match:      #1 1#
    no match:   # 11#
    no match:   #11 #
    no match:   # 11 #
    no match:   # 1 1 #
    match:      #1`~!@$^&*()-_=+|]}[{;'".><1#
    match:      #1`~!@$^&*()-_=1#
    no match:   #1~`!@$^&*()-_=+|]}[{;'".><#
    no match:   #~`!@$^&*()-_=+|]}[{;'".><1#
    no match:   #~`!@$^&*()-_=+|]}[{;'".><#

预期产量:

    match:      #1#
    match:      #1~`!l#
    match:      #11#
    match:      #111#
    match:      #1 1#
    no match:   # 11#
    no match:   #11 #
    no match:   # 11 #
    no match:   # 1 1 #
    match:      #1`~!@$^&*()-_=+|]}[{;'".><1#
    match:      #1`~!@$^&*()-_=1#
    match:      #1~`!@$^&*()-_=+|]}[{;'".><#
    match:      #~`!@$^&*()-_=+|]}[{;'".><1#
    match:      #~`!@$^&*()-_=+|]}[{;'".><#

信息:

Perl Version: v5.26.2
Platform: Ubuntu 18.10

2 个答案:

答案 0 :(得分:3)

\b是单词边界,它是单词字符和非单词字符之间的边界。

行首和行尾被视为非文字字符,因此,只有在第一个(最后一个)字符中有文字字符时,行尾或行首的\b才会“匹配”。

据我了解,您想拒绝以空格开头和/或结尾的行,请使用:

my $vars = [
    q#1#,
    q#1~`!l#,
    q#11#,
    q#111#,
    q#1 1#,
    q# 11#,
    q#11 #,
    q# 11 #,
    q# 1 1 #,
    q#1`~!@$^&*()-_=+|]}[{;'".><1#,
    q#1`~!@$^&*()-_=1#,
    q#1~`!@$^&*()-_=+|]}[{;'".><#,
    q#~`!@$^&*()-_=+|]}[{;'".><1#,
    q#~`!@$^&*()-_=+|]}[{;'".><#,
];

foreach my $var (@$vars){
    if ( $var =~ m/^(?!\h)[^\P{PosixPrint}\/\#\%\?\:\,\\]+(?<!\h)$/x) {
    #               ^^^^^^                                ^^^^^^^
        print "match:\t\t#$var#\n";
    }
    else{
        print "no match:\t#$var#\n";
    }
}

哪里

  • (?!\h)是负面的超前行为,可确保我们在第一个位置没有水平空间
  • (?<!\h)是一个否定性的回顾,它确保我们在最后一个位置没有水平空间

输出:

match:      #1#
match:      #1~`!l#
match:      #11#
match:      #111#
match:      #1 1#
no match:   # 11#
no match:   #11 #
no match:   # 11 #
no match:   # 1 1 #
match:      #1`~!@$^&*()-_=+|]}[{;'".><1#
match:      #1`~!@$^&*()-_=1#
match:      #1~`!@$^&*()-_=+|]}[{;'".><#
match:      #~`!@$^&*()-_=+|]}[{;'".><1#
match:      #~`!@$^&*()-_=+|]}[{;'".><#

答案 1 :(得分:2)

以下是先前答案提供的模式,并进行了一些修复:

/
   ^
   (?!\s)
   [^\P{PosixPrint}\\\/\#%?:,]*
   (?<!\s)
   \z
/x

以下是对上述内容的优化:

/
    ^
    (?: [^\P{PosixPrint}\s\\\/\#%?:,]++
        (?: [^\P{PosixPrint}\S]++
            [^\P{PosixPrint}\s\\\/\#%?:,]++
        )*+
    )?+
    \z
/x

一种更好的做法是声明允许哪些字符(白名单),而不是声明哪些字符(黑名单)。后一种方法容易出错。以下与上述解决方案相同,但使用白名单代替黑名单:

/
    ^
    (?: [a-zA-Z0-9!"\$&'()*+\-.;<=>@[\]^_`{|}~]++
        (?: [ ]++
            [a-zA-Z0-9!"\$&'()*+\-.;<=>@[\]^_`{|}~]++
        )*+
    )?+
    \z
/x

/
    ^
    (?: (?&SAFE_CHAR)++
        (?: [ ]++
            (?&SAFE_CHAR)++
        )*+
    )?+
    \z

    (?(DEFINE)
       (?<SAFE_CHAR> [a-zA-Z0-9!"\$&'()*+\-.;<=>@[\]^_`{|}~] )
    )
/x