Python:读取complete.js文件并更新该js文件中的特定方法

Python:读取complete.js文件并更新该js文件中的特定方法,python,Python,无论如何,我可以更新.js文件中的特定方法,而不干扰js文件中的其他脚本,我可以读取.js文件中的完整数据。您可以告诉我是否有任何方法或您可以共享任何参考来帮助我 例如: 在js文件中,我有一个函数“sendMessage({mode:n,delegatesFocus:r})” 我希望将其更新为“sendMessage({mode:'open'})” 我尝试使用substring,它只是替换了我给出的单词,我不需要它,我知道函数名,我需要更新“{}”括号内的文本,因为在这个js文件中,我使用了许

无论如何,我可以更新.js文件中的特定方法,而不干扰js文件中的其他脚本,我可以读取.js文件中的完整数据。您可以告诉我是否有任何方法或您可以共享任何参考来帮助我

例如: 在js文件中,我有一个函数“sendMessage({mode:n,delegatesFocus:r})” 我希望将其更新为“sendMessage({mode:'open'})”

我尝试使用substring,它只是替换了我给出的单词,我不需要它,我知道函数名,我需要更新“{}”括号内的文本,因为在这个js文件中,我使用了许多变量,比如“delegatesFocus”

谁能帮我一下吗

我的代码是

import os
rootdir = 'C:/Users/smith/testing/test.js'
with open(rootdir , 'r', encoding="utf8") as f:
lines = f.readlines()
for line in lines:
if 'sendMessage' in line:
print("sendMessage function is available")
          
使用此选项,我可以读取.js文件并检查函数是否可用,但我希望将函数从“sendMessage({mode:n,delegatesFocus:r})”重写为“sendMessage({mode:'open'})”

我被困在这里了,请帮帮我。
谢谢。

使用正则表达式:

import re

line = re.sub(
    r'sendMessage\(\{mode:n,\w+:r\}\)',
    "sendMessage({mode: 'open'})"
)

然后将
写回文件。

使用正则表达式:

import re

line = re.sub(
    r'sendMessage\(\{mode:n,\w+:r\}\)',
    "sendMessage({mode: 'open'})"
)

然后将
写回文件。

这种问题无法通过简单的方法(如字符串搜索和替换)可靠地解决。源代码对于这种方法来说太复杂了

正确的解决方案需要一个Javascript解析器。解析器将JS源代码转换为一棵树(“抽象语法树”,AST)。然后可以在该树结构中搜索所需的项(在本例中,是特定函数调用,或者更好的是,是特定函数调用的参数):

sendMessage({mode:n,delegatesFocus:r})
^-----------------------^我们在源代码中寻找这个范围
五--------------------------+
发送消息({|
模式:n,//注释|
delegatesFocus:r+——但也可能是这样,谁知道呢
})                                     |
^--------------------------------------+
一旦理解了源代码的含义,就不再关心源代码的格式、对象键的给定顺序、中间是否有注释,或者对象值是否引用了变量,如
n
r
、文字值,甚至是他们自己的复杂表达

有一个名为的全面JavaScript解析器,它已经被开发

Esprima将转换如下代码:

sendMessage({mode: n, delegatesFocus: r});
进入详细的抽象语法树(我为后人添加了一些注释):

对于我们的案例来说,除了我们可以用来定位想要的树节点的所有结构信息之外,有趣的一点是
范围
信息,因为它包含源代码字符串中的开始和结束位置,我们可以使用它以安全的方式修改JS源代码

方法是:

  • 从文件中读取JS源代码
  • 将其解析为AST
  • 使用节点访问者(请参见)查看树中的每个节点
  • 当一个节点满足严格的规范时,记住它在源代码中的开始和结束位置
  • 用新的JS代码替换它找到的所有位置,这很容易,因为解析器已经准确地告诉了我们剪切的位置
例如:

导入esprima
类MyVisitor(esprima.NodeVisitor):
“”“专注于一个特定函数调用的自定义节点访问者”“”
定义初始化(自):
self.found_ranges=[]
#我们只关心CallExpression节点(即函数调用)
def visit_CallExpression(self,node):
如果(node.callee.name=='sendMessage'和#函数名为'sendMessage`
len(node.arguments)==1和#它应该有1个参数
node.arguments[0]。类型=='ObjectExpression'和#这是一个对象
len(node.arguments[0].properties)==2和#,其中有两个属性
所有((p.key.name在['mode','delegatesFocus']中)#必须具有预期的名称
用于节点中的p。参数[0]。属性)
):
self.found\u ranges.append(节点.参数[0].范围)
#参观树上的其他一切
self.generic_访问(节点)
#阅读JS代码
将open('test.js',encoding='utf8')作为jsfile:
jscode=jsfile.read()
#解析范围信息,我们稍后需要
ast=esprima.parse(jscode,{'range':True})
#访问AST,这将填充查找到的范围列表
v=MyVisitor()
v、 访问(ast)
#我们需要从后面看源代码
#因为做任何改变都会弄乱我们的范围
对于开始,以反向结束(v.U范围):
code_before=jscode[:开始]
code\u after=jscode[end:]
打印('替换:',jscode[start:end])
jscode=code_before+“{mode:'open'}”+code_before
打印('\n---JS代码后------------------')
打印(jscode)
使用示例JS文件

函数示例(n,r){
sendMessage({mode:n,delegatesFocus:r});
}
//叫它
发送消息({
代表团焦点:错误,
模式:“文字值”
});
//这里有更多代码
它的输出是:

替换:{
代表团焦点:错误,
模式:“文字值”
}
替换:{mode:n,delegatesFocus:r}
---JS代码之后---------------------------------
函数样本(n,r){
sendMessage({mode:'open'});
}
//叫它
sendMessage({mode:'open'});
//这里有更多代码

这类问题无法通过简单的方法(如字符串搜索和替换)可靠地解决。源代码对于这种方法来说太复杂了

正确的解决方案需要一个Javascript解析器。解析器将JS源代码转换为一棵树(“抽象语法树”,AST)。然后可以在树结构中搜索所需的项(在本例中,是特定函数调用,或者更好的是,是特定函数的参数)