2017-11-05 17 views
2

をので、私は次の文字列正規表現で特定のタグを無視 - negitive先読み

This is an outside Example <p href="https://example.com"> This is a para Example</p><markup class="m"> this is a markup example</markup> 

を持っていると私は言葉example中のため、大文字と小文字を区別しない検索をしたい私のphpコードでこのシナリオを持っていますこの文字列が、

  • 私は、次の<markup ..> any content </markup>内検索を無視したい私の正規表現は(私は達成することができる午前)タグ属性
  • 内の例の発生を無視したいです完全
  • 今私は <markup>

    のためにそれを変更した私が今まで行ってきたが、

    /(example)(?:[^<]*>)/i

    これは正常に動作してhrefpのタグ、 内の例を無視

/(example)(?!([^<]*>)|(\<markup[^>]*>[^<]*<\/markup\>))/i

これは機能しません。 あなたは私の仕事を見ることができます - https://regex101.com/r/e2XujN/1

私はこの

で達成したい私は、次のよう

  • 場合と仮定して、マッチしたexample単語を交換します私はeXamPleを見つけました。
  • Example<markup>Example</markup>

によって置き換えされるというように、

注:マッチした文字列のパターンの場合、文字列を置き換える

+0

あなたは私に、これはDOMの@のPHPを使用して達成することができる方法の例を与えることができます。 –

+0

一致するサブストリングをsthに置き換えようとしていますか、それとも単に発生数を知っているだけですか? – revo

+0

私は大文字小文字を区別しないで 'example'の検索をしたいです。 と一致する' eXample'を ' eXample'に置き換えます。 注:置換文字列の場合は、一致した文字列と同じです。 –

答えて

1

同じであるあなたは、PCREで前提(*SKIP)(*F)を使用することができますパターン/文字列(ここではのマークアップ)で囲まれた特定の部分文字列と一致するようにスキップします。

(markup).*\1(*SKIP)(*F)|(example)(?![^<]*>)

説明:

除外サブストリング:第一キャプチャグループ
(マークアップ):文字は(大文字と小文字を区別しない)を文字通りマークアップと一致する
.*マッチ(行末を除く)任意の文字
\1試合1番目のキャプチャグループと同じテキスト
(*SKIP)より
(*F)(* FAIL)の略語は一致しません

+0

答えをありがとう。新しいものを学ぶことになった。本当に私の一日を救った –

+0

ようこそ。後見では、私はこのように閉じた&lazyパターンを使います:['<マークアップ* *? (*!SKIP)(*!F)|(例)(?!<]*>) '](https://regex101.com/r/y1j5t6/2)一行でそれは重要です。 – wp78de

1

最初の問題と同じ方法で解決できます。文字列の直後に閉じタグがないかどうかを確認します。

正規表現:

(example)(?![^<]*>)(?![^<]*<\/markup\>)

Demo

+0

私はそれが好きですが、 -substringにタグがあると失敗します:https://regex101.com/r/AH5EQx/1 – wp78de

+0

はい、これは間違いなく私の問題を解決しますが、@ wp78deは正しいです。彼の解決策はもっと簡単です。努力をいただきありがとうございます。 –

0

答えはDOMを使用しているが、しかし、それはテキストノードで動作するように少しトリッキーだし、それらの中にHTMLコンテンツを挿入します。

PHP live demo

$content = <<< 'HTML' 
This is an outside Example <p href="https://example.com"> This is a para Example</p> 
test <markup class="m"> this is a markup example</markup> another example <p>example</p> 
HTML; 

// Initialize a DOM object 
$dom = new DOMDocument(); 
// Use an HTML element tag as our HTML container 
// @hakre [https://stackoverflow.com/a/29499718/1020526] 
@$dom->loadHTML("<div>$content</div>"); 

$wrapper = $dom->getElementsByTagName('div')->item(0); 
// Remove wrapper 
$wrapper = $wrapper->parentNode->removeChild($wrapper); 
// Remove all nodes of $dom object 
while ($dom->firstChild) { 
    $dom->removeChild($dom->firstChild); 
} 
// Append all $wrapper object nodes to $dom 
while ($wrapper->firstChild) { 
    $dom->appendChild($wrapper->firstChild); 
} 

$dox = new DOMXPath($dom); 
// Query all elements in addition to text nodes 
$query = $dox->query('/* | /text()'); 

// Iterate through all nodes 
foreach ($query as $node) { 
    // If it's not an HTML element 
    if ($node->nodeType != XML_ELEMENT_NODE) { 
     // Replace desired word/content 
     $newContent = preg_replace('~(example)~i', 
      '<markup>$1</markup>', 
      $node->wholeText); 
     // We can't insert HTML directly into our node 
     // so we need to create a document fragment 
     $newNode = $dom->createDocumentFragment(); 
     $newNode->appendXML($newContent); 
     // Replace new content with old one 
     $node->parentNode->replaceChild($newNode, $node); 
    } 
} 

// Save modifications 
echo $dom->saveHTML($dom); 
+0

本当にありがとうございます。これは

タグ内の 'example'もスキップします。 タグ内の例をスキップしてください。だから、あなたの例のための予想される出力は 'これは外これは例パラある

テスト<マークアップクラス="メートルであるべきです">これはマークアップの例です別のの例

' –

関連する問題