web-dev-qa-db-ja.com

正規表現-一致する文字列の一部を無視します

これが私の文字列です:

address='St Marks Church',notes='The North East\'s premier...'

match_allを使用してさまざまなパーツを取得するために使用している正規表現は

'/(address|notes)='(.+?)'/i'

結果は次のとおりです。

住所=>セントマークス教会
notes =>北東部\

ノートの\ '文字を無視するにはどうすればよいですか?

10
Paul Phillips

文字列をヒアドキュメントでラップするのか二重引用符でラップするのかはわかりませんが、欲張りなアプローチではありません。

$str4 = 'address="St Marks Church",notes="The North East\'s premier..."';
preg_match_all('~(address|notes)="([^"]*)"~i',$str4,$matches);
print_r($matches);

出力

Array
(
    [0] => Array
        (
            [0] => address="St Marks Church"
            [1] => notes="The North East's premier..."
        )

    [1] => Array
        (
            [0] => address
            [1] => notes
        )

    [2] => Array
        (
            [0] => St Marks Church
            [1] => The North East's premier...
        )

)

Preg_splitを使用した別のメソッド:

//split the string at the comma
//assumes no commas in text
$parts = preg_split('!,!', $string);
foreach($parts as $key=>$value){
    //split the values at the = sign
    $parts[$key]=preg_split('!=!',$value);
    foreach($parts[$key] as $k2=>$v2){
        //trim the quotes out and remove the slashes
        $parts[$key][$k2]=stripslashes(trim($v2,"'"));
    }
}

出力は次のようになります。

Array
(
    [0] => Array
        (
            [0] => address
            [1] => St Marks Church
        )

    [1] => Array
        (
            [0] => notes
            [1] => The North East's premier...
        )

)

超遅いオールドスクール方式:

$len = strlen($string);
$key = "";
$value = "";
$store = array();
$pos = 0;
$mode = 'key';
while($pos < $len){
  switch($string[$pos]){
    case $string[$pos]==='=':
        $mode = 'value';
        break;
    case $string[$pos]===",":
        $store[$key]=trim($value,"'");
        $key=$value='';
        $mode = 'key';
        break;
    default:
        $$mode .= $string[$pos];
  }

  $pos++;
}
        $store[$key]=trim($value,"'");
5
AbsoluteƵERØ

したがって、バックスラッシュが前に付いていない終了引用符まで一致させる必要があります。

(address|notes)='(.*?)[^\\]'

この [^\\]は、 '文字の直前の文字をバックスラッシュ以外のものにします。

1

_match_all_を使用していることを投稿し、プロファイルの上位タグはphpwordpressであるため、phpでpreg_match_all()を使用していると想定するのは妥当だと思います。

次のパターンは、目的の連想配列を構築するために必要な部分文字列と一致します。

フルストリングマッチと1つのキャプチャグループを生成するパターン:

  1. /(address|notes)='\K(?:\\\'|[^'])*/(166ステップ、 デモリンク
  2. /(address|notes)='\K.*?(?=(?<!\\)')/(218ステップ、 デモリンク

2つのキャプチャグループを生成するパターン:

  1. /(address|notes)='((?:\\\'|[^'])*)/(168ステップ、 デモリンク
  2. /(address|notes)='(.*?(?<!\\))'/(209ステップ、 デモリンク

コード:( デモ

_$string="address='St Marks Church',notes='The North East\'s premier...'";

if(preg_match_all("/(address|notes)='\K(?:\\\'|[^'])*/",$string,$out)){
    $result=array_combine($out[1],$out[0]);
}
var_dump($result);

echo "\n---\n";

if(preg_match_all("/(address|notes)='((?:\\\'|[^'])*)/",$string,$out,PREG_SET_ORDER)){
    $result=array_combine(array_column($out,1),array_column($out,2));
}
var_dump($result);
_

出力:

_array(2) {
  ["address"]=>
  string(15) "St Marks Church"
  ["notes"]=>
  string(28) "The North East\'s premier..."
}

---
array(2) {
  ["address"]=>
  string(15) "St Marks Church"
  ["notes"]=>
  string(28) "The North East\'s premier..."
}
_

パターン#1と#3は、代替を使用して、バックスラッシュが前に付いていない非アポストロフィ文字またはアポストロフィを許可します。

パターン#2と#4(php demo で実装する場合は、追加のバックスラッシュが必要になります)は、バックスラッシュが前に付いたアポストロフィが一致を終了しないようにルックアラウンドを使用します。

いくつかの注意:

  • キャプチャグループ、代替案、およびルックアラウンドを使用すると、パターンの効率が低下します。これらのコンポーネントの使用を制限すると、パフォーマンスが向上します。否定文字クラスを使用すると、パフォーマンスが向上することがよくあります。

  • _\K_(完全な文字列の一致を再開する)を使用すると、キャプチャグループを削減しようとするときに役立ち、出力配列のサイズが削減されます。

1
mickmackusa