如何使用preg_replace用html标签中的下划线替换连字符?

时间:2017-02-08 15:14:31

标签: php preg-replace preg-match

我正在尝试仅在divinput ID内使用下划线替换连字符。以下是我没有成功的尝试。我的代码替换了连字符,但在错误的地方执行。

它应该只替换字符串中的连字符,例如id="input-field-1"id="input-field-1"等。外部类中的所有连字符都应保持原样。

$string =
'<div class="block-wrapper">'.
    '<div class="block">'.
        '<div id="bl-inner-id-1" class="block-inner"></div>'.
            '<input id="input-field-1" class="input" type="radio">'.
    '</div>'.
    '<div class="block">'.
        '<div id="bl-inner-id-2" class="block-inner"></div>'.
            '<input id="input-field-2" class="input" type="radio">'.
    '</div>'.
'</div>';

$search1 = "/[^\<div id\=\"](-)[^class\=\"block\">]/";
$search2 = "/[^\<input id\=\"](-)[^type\=\"radio\">]/";
$replace = "_";

echo preg_replace($search1, $replace, $string);

echo preg_replace($search2, $replace, $string);

我只想知道如何使用preg_replace执行此操作。 preg_replace_callback可能不适合我的具体情况。

1 个答案:

答案 0 :(得分:0)

我同意像Javascript这样的DOM解析器更适合这类任务,正如Dimi在问题评论中提到的那样。话虽这么说,我可以理解为什么可能需要使用PHP,例如特定项目的约束。

仅使用preg_replace可能会导致问题,因为我们始终不知道ID文本在<div><input>标记中的位置(除非HTML字符串)总是以非常具体的方式格式化)。因此,执行正则表达式匹配以仅在div / input标记内查找id属性很可能需要variable length lookbehind assertions,这在大多数正则表达式实现中都不受支持。

您可以尝试将字符串分解为单独的组件,然后替换每个id的文本块,而不是使用单个正则表达式替换所有超出部分。我在下面添加了一个有用的PHP示例,并解释了PHP注释中的每个步骤:

$string =
'<div class="block-wrapper">'.
    '<div class="block">'.
        '<div id="bl-inner-id-1" class="block-inner"></div>'.
            '<input id="input-field-1" class="input" type="radio">'.
    '</div>'.
    '<div class="block">'.
        '<div id="bl-inner-id-2" class="block-inner"></div>'.
            '<input id="input-field-2" class="input" type="radio">'.
    '</div>'.
'</div>';

// Find <div> and <input> start tags in the string and store their contents in an array
preg_match_all('/<(div|input)[^>]+>/', $string, $div_input);

// Loop through the array of <div> and <input> tags
foreach ($div_input[0] as $old_tag) {
    // Array element [0] was selected here because preg_match_all also returns
    // the parenthesized subpattern results as $div_input[1], $div_input[2], etc

    // Find id attributes containing a hyphen in the current HTML tag
    preg_match('/ id="[^"]*-[^"]*"/', $old_tag, $id_text);

    // Only proceed if a match was found
    if (!empty($id_text[0])) {

        // Create a new string for the current tag and replace the hypens in the id text
        $new_tag = str_replace($id_text[0], str_replace('-', '_', $id_text[0]), $old_tag);

        // Replace the current tag with the new corrected one in the main HTML string
        $string = str_replace($old_tag, $new_tag, $string);
    }
}

echo $string;