2017-11-28 3 views
0

文字列内の単語のインスタンスを1つだけ一致させるにはどうすればよいですか? 例として、テスト・ワードとして "fred"を使用すると、 "fredwilmawilliamjohn"という文字列の一致はTRUEになりますが、 "fredwilmawilliamfred"はFALSEにする必要がありますか?文字列内の単語のインスタンスを1つだけ見つけるにはどうすればよいですか?

+4

Perl_の学習で演習を行っている場合は、自分で行うべきです。 – simbabque

答えて

2

リストの文脈で/gフラグを使用して一致数を数え、それをスカラーコンテキストに変換することができます。

use strict; 
use warnings; 
use feature 'say'; 

for my $string (qw(fredwilmawilliamjohn fredwilmawilliamfred)) { 
    my $count =() = $string =~ m/(fred)/g; 
    if ($count == 1) { 
     say $string; 
    } 
} 

最も関連性の高い部分がリストコンテキストに試合を強制=() =、です。 my $countは、マッチのリストをスカラーコンテキストに強制します。スカラーコンテキストでは、リスト内の項目の数がわかります。それがあなたの試合の数です。

+0

これは純粋にregexpを使ってできますか? $ _ = "fredwilliamwilma"; if(/ regexp /) {print "文字列にfredが1つしかありません"} – SKS

+0

@SKSというのは、すべてのロジックをパターンに入れたいということですか?フレッドとネガティブなことは、何もない、あるいはフレッドの後ろを先に見ています。今はコンピュータを持っていない。あなたは自分自身を試してみる必要があります。 – simbabque

+1

'=()='は 'goatse operator'とも呼ばれます:) – Sobrique

0

パターンにマッチして、それが文字列に続いて現れないことを確認したいと思うようです。否定先読みを使ってどのようにこのことについて、

m/fred(?!.*fred)/ 

は、それを破壊:

を?! -

が続いていません。* - ゼロ以上の文字

+0

regexpが否定的な先読みを成功させようとするため、これは機能しません。 2番目のfredと一致しない文字列内に何かが見つかると、正規表現は成功します。 '!m/fred(?= * fred)/'はここで動作します。 –

+0

@ChrisCharley原則は正しいですが、あなたはそれを正しく言っているわけではありません。この正規表現は最初のfredとのマッチングを避けますが、正規表現の先頭は文字列内でさらに試され、2番目のfredとマッチします(後にfredはありません) – ysth

+0

@ysthエラー。私は正規表現がどのように機能するかを正確に見ています。 –

1
/fred(*COMMIT)(?!.*?fred)/s 

(*COMMIT)(5.10で追加)fredに一致した後、バックトラックと場合には、再度の残りの部分をそれに一致しようとしていないと言います正規表現は失敗します。正規表現の残りの部分は、.*?fred(任意の文字の後ろにfredが続きます)が、最初のfredの後、つまりそれ以上のfredがない場合、その時点で一致すると一致しません。

5.10前に、あなただけのようにのように文字列の最初のフレッドと一致するように正規表現の最初のフレッドを強制する必要があります:

/^(?:(?!fred).)*+fred(?!.*?fred)/s 

は(限りそうでないとして任意の数の文字と一致しますfredの始まりとfredとのマッチングの前に別のfredが続くことはできません)。

それとも

/^(?>.*?fred)(?!.*?fred)/s 

(文字列の先頭から開始し、バックトラッキングを許可せず、最初のフレッドを見つけ、fredはそれの後に存在しないことを主張する)

(/、全体を通じてsは、.を改行文字以外の文字にマッチさせるために使用されます)。

関連する問題