2012-03-17 74 views
-2

我试图匹配一个字符串,使得最左边的符号和最右边的符号是相同的。我怎么做?perl中最右边和最左边的符号与正则表达式匹配

+0

定义的“符号”。 – tchrist 2012-03-17 22:39:38

+0

@tchrist,任何字母数字字符。我只是想要一个正式的答案。我可以自己构建表达式。 – gzg 2012-03-17 22:44:54

+2

符号是'\ pS';字母是'\ pL';数字是'\ pN';字母是'\ p {alpha}',它包含各种标记和符号,并排除某些数字。我给你一个正式的答案。 – tchrist 2012-03-17 22:49:57

回答

1
$string =~ m/^(.).*\1$/ 

应该工作。但是,这无法匹配长度为1的字符串。

+0

我认为(。)将第一个符号分组,并且\ 1表示第一个分组。我对吗? – gzg 2012-03-17 22:36:21

+1

是的。我只是添加了一个链接到我的答案与更多的信息给你。 – 2012-03-17 22:37:45

+0

恐怕@gzg增加了更多的规定,所以你的模式不再符合他的要求。 – tchrist 2012-03-17 22:51:11

2

这是不可能确切地知道你的意思不明确的,你认为什么是“符号”,但这里是一个可能的解决方案:

use Unicode::Normalize; 
NFD($string) =~/\A \s* ((?= \p{Grapheme_Base}) \X) .* \1 \s* \z /sx; 

,这里是另一个:

use Unicode::Normalize; 
NFD($string) =~/\A \s* ((?= \p{Symbol}) \X) .* \1 \s* \z /sx; 

和这里是一个多:

use Unicode::Normalize; 
NFD($string) =~/\A \s* ((?: (?= \p{Symbol}) \X)+) .* \1 \s* \z /sx; 

而且你也许可以在某些甚至有可能非常有限的情况下能够与闪避:

$string =~/^ (\pS) .* \1 $ /xs; 

但是,如果你这样做,它也有可能有一天你会希望你多加小心。

+0

谢谢。我会试一试;看起来会有帮助。 – gzg 2012-03-17 22:51:29

1

为什么你想用正则表达式来做这个?它是功课吗?我避免了像这样的微小模式的正则表达式。

use Unicode::Normalize qw(NFC); 
$s = NFC($s); 

substr($s, 0, 1) eq substr($s, -1, 1); 

因为汤姆会抱怨字符与字形,你可以处理它:

use v5.10.1; 
use Unicode::GCString; 
use Unicode::Normalize qw(NFC); 

my $gcs = Unicode::GCString->new(NFC($s)); 
$gcs->substr(0, 1) eq $gcs->substr(-1, 1) 
+1

我很确定你想要'$ gcs-> substr(0,1)'和'$ gcs-> substr(-1,1)'。即便如此,还是有问题的,因为除非双方首先被归一化为相同的形式,否则这并不总是奏效。好吧,你可以调用'Unicode :: Collat​​e-> new-> eq($ gcs-> substr(0,1),$ gcs-> substr(-1,1))',但这已经失控;最好先进行标准化。 - 但大多数情况下,我很担心要从中获得正确的打印字符,而不是空白或控制字符或孤立标记,并且要有空格。 – tchrist 2012-03-17 23:06:59

+0

是的,总是正常化。你的建议是什么使得这个IO层(或者我们刚刚在电子邮件中谈到的东西?) – 2012-03-17 23:13:13

+1

不,你不能使用' - > as_string',因为你会产生类似于'“\ x {305} xxx b \”{“}”。你必须使用真正的' - > substr'方法来处理字形,而不是'substr'函数处理代码点。 - 我前段时间可能在p5p上提到了I/O层的东西;我不记得。我想我给你发了一些代码,用双前台后台处理模拟这些代码。 – tchrist 2012-03-17 23:17:21

0

这些正则表达式的匹配字符串长度为1和更大。在表达式中,(.)代表一个捕获组,其中点应该用您认为符合您的类别的符号替换(请参阅Unicode guru's,尽管这似乎不是问题的意图)。

此正则表达式的上下文是单行(/s修饰符)。它允许点匹配 新行以及其他任何东西(如[\s\S]),因此可以嵌入新行,也可以作为绝大多数分隔符。

使用\z相同$(在/s模式),除了\z校正一个场景,其中可以$换行符之前匹配(在字符串的末尾匹配更commona)。如果有问题的字符是换行符,并且使用了非贪婪量词(如.*?),并且目标字符串是“\ nasdf \ n \ n”,则它可能在最终换行符之前进行虚假匹配。但这是一个没有实际意义的问题,因为比赛都是贪婪的。尽管如此,请留下咧嘴笑。

/^(?=(.)).*\1\z/s 

膨胀

/ 
^   # Beginning of string 
(?=(.))  # Lookahead - capture grp1, first (any) character (but don't consume it) 
.*   # Optionally consume all the characters up until before the last character 
\1   # Backreference to capture grp1, this must exist 
\z   # End of string 
/s # s modifier 

实施例只是规定词类字符

/^(?=(\w)).*\1\z/s 

同样,只是替换您上可接受的符号

+0

'/ s'对'$'锚点没有影响。你正在考虑'/ m'。 '/ s'只是让一个。匹配换行符。然而,默认的'/ m'会让你的'^'匹配逻辑行的开头,这就是为什么Tom使用'\ A'的原因。 \ w'也可以匹配比字母数字更多的字符。它是任何标识符字符。 – 2012-03-18 00:49:38

+0

@brian d foy - 正在解释/^(?=(.)).*\1$/,/^(?=(.)).*?\1$/s,/ ^(?)的不同效果。 =(。))。* \ 1 $/s,/^(?=(.)).*?\1\z/s,/^(?=(.)).*\1\z/s when匹配“\ n”,“\ n \ n”或“\ n \ n \ n”的目标字符串。如果'\ n'不是可选字符,它的模拟。我想我可以使用'/ ^(?=([^ \ W _]))。* \ 1 \ z/s'作为一个更广泛的规定,谢谢你的支持。并感谢为我打开我的帖子。 – sln 2012-03-18 01:56:55

相关问题