【问题标题】:Regex replacement of a partial string inside JS file正则表达式替换 JS 文件中的部分字符串
【发布时间】:2018-10-06 06:44:24
【问题描述】:

我有以下 PHP 正则表达式问题,可能无法解决。

我需要通过用函数调用替换某些子字符串来预处理 JS 文件。

所以基本上转这个:

var s = "I'll sleep all day when I'm tired";

进入这个:

var s = "I'll sleep all "+getPreference()+" when I'm tired";

到目前为止一切顺利,唯一的问题是我不知道原始JS中使用哪种引号作为字符串分隔符。

字符串也可以是这样的:

var s = 'I\'ll sleep all day when I\'m tired';

这会导致:

var s = 'I\'ll sleep all "+getPreference()+" when I\'m tired';

它只会在执行 JS 时将我的函数调用显示为字符串的一部分。

长话短说,我需要一种安全的方法来确定使用哪个字符串分隔符(" 或 '),然后相应地修改替换字符串。

这里有任何正则表达式天才有想法吗?非常感谢您的帮助。

更新:

非常感谢到目前为止的帮助。 我觉得我没有提供足够的背景信息。

  • 正则表达式应该在 PHP 中完成(预处理 JS)而不是通过 JS 中的函数。
  • 我什么都不知道,也不能假设关于 JS 的任何事情(例如字符串的开头或结尾),除非它是有效代码。
  • 我确切地知道要替换什么,这不是问题。

考虑这个例子:

     message = Theme.addToCartSuccess.replace("**product**", 
     item.title).replace(
     "**cart_link**", 
     "<a href=\"/cart\">\n    REPLACE_ME\n</a>")
     .replace("**continue_link**", 
     "<a\n    href=\"/collections/all\"\n>\n    
     REPLACE_ME\n</a>").replace("**checkout_link**", "<a 
     href=\"/checkout\">\n    REPLACE_ME\n</a>");
      return setTimeout(function() {
       _this.productMessages.html(message).addClass("success- 
      message").removeClass("error-message");

在上面的例子中,我需要用 getVar() 替换字符串 REPLACE_ME

更新 2:

我觉得解决这个问题的唯一解决方案是从替换字符串中回溯并分析可能的分隔符:

\" > 分隔符必须是 "
\' > 分隔符必须是'
' 或 " > 可以是,进一步回溯,直到我们遇到 ; > ; 之前的最后一个引号必须是分隔符。

想法?

谢谢, 汤姆

【问题讨论】:

  • 我认为主要问题不是引号,而是应该在哪里插入这个函数。
  • 快速提问。你不能简单地检查结尾;之前的分隔符类型吗?
  • 这很简单,给我几分钟,你怎么知道在哪里插入。
  • Regex 不是用于操作 JavaScript 的合适工具。您需要解析它并重新构建它。或者只是使用查找和替换对您的源代码运行一次“预处理”,也许......
  • 不要担心在哪里插入函数调用,这不是问题。我在这里强烈简化了它,但只是假设它总是需要替换“day”这个词。

标签: javascript php regex preg-replace


【解决方案1】:

使用捕获组和反向引用:

var line = 'var s = "I\'ll sleep all day when I\'m tired";'
new_line = line.replace(/(["'])(I.*ll sleep all ).* (when I.*m tired)\1;/, "$1$2$1 + getPreference() + $1$3$1;");
console.log(new_line);

line = "var s = 'I\\'ll sleep all day when I\\'m tired';"
new_line = line.replace(/(["'])(I.*ll sleep all ).* (when I.*m tired)\1;/, "$1$2$1 + getPreference() + $1$3$1;");
console.log(new_line);

在正则表达式中,您可以使用 \1 返回捕获组 1,在替换中您使用 $1

【讨论】:

  • 一个肮脏的,快速的答案只是表明它有效。不是一个好主意。
  • 这是为了展示使用捕获组背后的原理。我真的不知道他到底想匹配什么。
  • 对不起,我不记得我之前是否对你投过反对票。但这次我做到了。
【解决方案2】:

给你

function test( $string ){
    $pattern = '/^(var\s+s\s*=\s*)(\'|")(.+)(day)(.+\2\s*;)/';
    echo preg_replace_callback($pattern, function($match){
        return $match[1].$match[2].$match[3].$match[2].'+getPreference()+'.$match[2].$match[5];
    }, $string);
    echo "\n";
}

我假设您想用该函数替换 day

你可以测试一下here

而测试字符串就是这些

test( <<<STR
var s = "I'll sleep all day when I'm tired";
STR
);

test( <<<STR
var s = 'I\'ll sleep all day when I\'m tired';
STR
);

别担心&lt;&lt;&lt;HEREDOC 我真的不想解释它,它只是一种不用引号的方式来处理字符串。

哦,输出是这样的

var s = "I'll sleep all "+getPreference()+" when I'm tired";
var s = 'I\'ll sleep all '+getPreference()+' when I\'m tired';

PS。不用preg_replace_callback 也可以,我只是想让它更花哨,因为这看起来很无聊。

function test( $string ){
    $pattern = '/^(var\s+s\s*=\s*)(\'|")(.+)(day)(.+\2\s*;)/';
    echo preg_replace($pattern, '\1\2\3\2'.'+getPreference()+'.'\2\5', $string);
    echo "\n";
}

这当然是针对这个答案非常具体的,它只适用于 var s = 某事 day 某事...但您必须提供更多上下文才能使其更通用。

更新

我将(var\s+s\s+=\s+) 更改为(var\s+s\s*=\s*),因为您可以使用不带空格的var s="..."

干杯。

【讨论】:

    猜你喜欢
    • 2017-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 2020-02-20
    • 2021-05-25
    • 1970-01-01
    相关资源
    最近更新 更多