2009-06-29 10 views
5

私はすべてにマッチする正規表現を書こうとしていますが、エスケープされていないアポストロフィはありません。以下を考慮してください:正規表現で文字列を一致させるときにエスケープされた引用符を無視する方法はありますか?

<?php $s = 'Hi everyone, we\'re ready now.'; ?> 

私の目標は、基本的にその文字列部分と一致する正規表現を書くことです。私は単純な文字列を一致させるために

/.*'([^']).*/ 

ような何かを考えていますが、私は否定後読みは、それがが付いていないことを確認するために、そのアポストロフィに取り組んで取得する方法を見つけ出すしようとしてきましたバックスラッシュ...

アイデア?

- JMT

答えて

3
<?php 
$backslash = '\\'; 

$pattern = <<< PATTERN 
#(["'])(?:{$backslash}{$backslash}?+.)*?{$backslash}1# 
PATTERN; 

foreach(array(
    "<?php \$s = 'Hi everyone, we\\'re ready now.'; ?>", 
    '<?php $s = "Hi everyone, we\\"re ready now."; ?>', 
    "xyz'a\\'bc\\d'123", 
    "x = 'My string ends with with a backslash\\\\';" 
    ) as $subject) { 
     preg_match($pattern, $subject, $matches); 
     echo $subject , ' => ', $matches[0], "\n\n"; 
} 

プリント

<?php $s = 'Hi everyone, we\'re ready now.'; ?> => 'Hi everyone, we\'re ready now.' 

<?php $s = "Hi everyone, we\"re ready now."; ?> => "Hi everyone, we\"re ready now." 

xyz'a\'bc\d'123 => 'a\'bc\d' 

x = 'My string ends with with a backslash\\'; => 'My string ends with with a backslash\\' 
+0

テストケースを提供したために投票しました。 –

2
/.*'([^'\\]|\\.)*'.*/ 

は括弧で囲まれた部分は、非アポストロフィ/バックスラッシュとバックスラッシュでエスケープ文字を探します。特定の文字のみをエスケープできる場合は、\\.を​​などに変更してください。背後にある負の表情経由

+0

が、それは病的なケースを処理しません... 「私の文字列は、バックスラッシュでで終わる\\」 –

+0

おかげジョン:あなたが$ 2の引用符で囲まれていない文字列をキャプチャすることができます!幸いなことに、私が対処しなければならないケースは抑えられ、.jxcが記述する問題には決して到達しません。非常に簡単な解決策、私は本当に考えるべきだった。再びありがとう! :) – JMTyler

0

/ 
.*?'    #Match until ' 
(
.*?    #Lazy match & capture of everything after the first apostrophe 
)  
(?<!(?<!\\)\\)' #Match first apostrophe that isn't preceded by \, but accept \\ 
.*    #Match remaining text 
/
0
Regex reg = new Regex("(?<!\\\\)'(?<string>.*?)(?<!\\\\)'"); 
3

ここでのテストケースと私のソリューションです:

/.*?'((?:\\\\|\\'|[^'])*+)'/ 

そして、私の(Perlのが、私は考えていない任意のPerlの固有の機能は使用しないでください)証明:

use strict; 
use warnings; 

my %tests =(); 
$tests{'Case 1'} = <<'EOF'; 
$var = 'My string'; 
EOF 

$tests{'Case 2'} = <<'EOF'; 
$var = 'My string has it\'s challenges'; 
EOF 

$tests{'Case 3'} = <<'EOF'; 
$var = 'My string ends with a backslash\\'; 
EOF 

foreach my $key (sort (keys %tests)) { 
    print "$key...\n"; 
    if ($tests{$key} =~ m/.*?'((?:\\\\|\\'|[^'])*+)'/) { 
     print " ... '$1'\n"; 
    } else { 
     print " ... NO MATCH\n"; 
    } 
} 

が実行している、これは示しています

$ perl a.pl 
Case 1... 
... 'My string' 
Case 2... 
... 'My string has it\'s challenges' 
Case 3... 
... 'My string ends with a backslash\\' 

注意をその時の初期のワイルドカード開始は非貪欲である必要があります。それから、私は非バックトラッキングマッチを使って\\と\ 'をぐらつぶしてから、スタンドアロンの引用文字ではないものを使用します。

私はこれがおそらくコンパイラの組み込みのアプローチを模倣していると思います。

0

これではJavaScript用です:

/('|")(?:\\\\|\\\1|[\s\S])*?\1/

それ...

  • マッチ単一または二重引用符で囲まれた文字列
  • 試合空の文字列(長さ0)
  • マッチ文字列と埋め込み空白(\n\tなど)内側
  • スキップは、単一または二重引用符()二重引用符内
  • スキップ単一引用符を脱出し、その逆

にのみ最初の引用が捕捉されます。非常に近い

/('|")((?:\\\\|\\\1|[\s\S])*?)\1/

関連する問題