允许Posix打印字符,%\ /#除外? :并且除了字符串开头和结尾的空格外

问题描述 投票:0回答:2

所以对于这个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";
    }
}

OUTPUT:

    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
regex perl pcre
2个回答
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:      #~`!@$^&*()-_=+|]}[{;'".><#

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
© www.soinside.com 2019 - 2024. All rights reserved.