2012-03-17 45 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