4

ここに行きます:

私はPHPアプリケーションをコーディングしていますが、そのための新しい公式ドメインがあり、ここにすべてのFAQがあります。スクリプト内の一部のファイルには、古いFAQドメインへのヘルプリンクが含まれているため、新しいドメインを使用してそれらを置き換えたいと思います。ただし、コメントまたはコメントブロックの下にある場合にのみ、古いドメインにリンクしているURLを保持したいと思います(自己参照やその他のドキュメントに古いドメインを使用しています)。

したがって、基本的に、私が達成したいのは、次の場合に機能する正規表現です。

  1. すべての行で出現example.comするすべての行に一致します*。
  2. 行全体と一致させるのではなく、example.com文字列のみと一致させてください。
    • //行が、、、/*または「*」で始まる場合example.com、その1行のどのインスタンスとも一致しません(ただし、コメントブロックが開かれたのと同じ行で閉じられている場合、これは問題になる可能性があります)。

私は通常、次のようにブロックコメントを書きます。

/* text
 * blah 
 * blah
*/

そのため、「example.com」が、、、または「*」の後//にある場合は、「example.com」と一致させたくありません。/*

私はそれがこのようなものになるだろうと思いました:

^(?:(?!//|/\*|\s\*).?).*example\.com

ただし、これには1つの問題があります。「example.com」だけではなく、行全体に一致します(これにより、主に2つ以上の「example.com」文字列が1行に一致する場合に問題が発生します)。

誰かが私の正規表現を修正するのを手伝ってもらえますか?注:grepWinなどのツールを使用して、すべてのファイルを一度にローカルで編集できるため、PHP正規表現である必要はありません。

ああ、次のようにブロックコメントを一般化する方法があるかどうか教えてください。一度見つかったら、見つかるまで/*一致させないでください。それは非常に便利です。example.com*/一般的な(言語に依存しない)正規表現でそれを実現することは可能ですか?

4

2 に答える 2

2

ある種のトークナイザーを使用して、コメントと他の言語トークンを区別します。

PHP ファイルを処理しているので、PHP 独自のトークナイザー関数token_get_allを使用する必要があります。

$tokens = token_get_all($source);

次に、トークンを列挙し、トークンをタイプ別に分けることができます。

foreach ($tokens as &$token) {
    if (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT, T_ML_COMMENT))) {
        // comment
    } else {
        // not a comment
        $token[1] = str_replace('example.com', 'example.net', $token[1]);
    }
}

最後に、すべてを で元に戻しimplodeます。

手元に適切なトークナイザーがない他の言語については、独自の小さなトークナイザーを作成できます。

preg_match_all('~/\*.*?\*/|//(?s).*|(example\.com)|.~', $code, $tokens, PREG_SET_ORDER);
foreach ($tokens as &$token) {
    if (strlen($token[1])) {
        $token = str_replace('example.com', 'example.net', $token[1]);
    } else {
        $token = $token[0];
    }
}
$code = implode('', $tokens);

これは、文字列のような他のトークンを考慮していないことに注意してください。したがってexample.com、文字列だけでなく、次のような「コメント」にも含まれている場合、これは一致しません。

'foo /* not a comment example.com */ bar'
于 2012-07-29T08:29:44.197 に答える
2

コメント セクション内にない場合にのみ一致する正規表現example.com(ただし、行コメントは気にしないため、これを個別に行う必要があります):

$result = preg_replace(
    '%example\.com # Match example.com
    (?!            # only if it\'s not possible to match
     (?:           # the following:
      (?!/\*)      #  (unless an opening comment starts first)
      .            #  any character
     )*            # any number of times
     \*/           # followed by a closing comment.
    )              # End of lookahead
    %sx', 
    'newdomain.com', $subject);
于 2012-07-29T08:08:20.317 に答える