如何编写正则表达式以括号替换数学函数的所有括号,但忽略所有其他括号?
以下是一些示例输入:
x(n)+(y(n)+1)*n
x(n(a,b),a,b)+2^(y(n(a,b)+a+b)+1)
x(n)+(y(n)/(N(n)))
我希望他们的相应输出为:
x[n]+(y[n]+1)*n
x[n[a,b],a,b]+2^(y[n[a,b]+a+b]+1)
x[n]+(y[n]/(N[n]))
这是我设法乱涂乱画的。
require 'rubygems'
require 'mechanize'
CSV.open('C:\Users\hp1\Desktop\output.txt', "wb") do |index|
f = File.open('C:\Users\hp1\Desktop\input.txt', "r")
f.each_line { |line|
fn = line
fn=fn.gsub(/(?[a-zA-Z0-9])\[+-*"/",]/, /[?[a-zA-Z0-9]]\[+-*"/",]/)
index<<line
end
}
end
但它不起作用。
编辑:函数表示f(x)
,f(x,y)
等格式的任何内容。非函数的格式为x+y
,{{1}因此,需要将表达式x*y
转换为f(x(y)+m(n)+(a+b))
。
答案 0 :(得分:4)
只需使用一个简单的循环,并从里到外替换嵌套的括号对。
s = "x(n)+(y(n)+1)*n\nx(n(a,b),a,b)+2^(y(n(a,b)+a+b)+1)\nx(n)+(y(n)/(N(n)))\nf(x(y)+m(n)+(a+b))"
while s.gsub!(/(\w+)\(([^()]+)\)/, '\1[\2]')
s.gsub!(/(\W)\(([^()]+)\)/, '\1{\2}')
end
s.gsub!(/{/, "(")
s.gsub!(/}/, ")")
puts s
# x[n]+(y[n]+1)*n
# x[n[a,b],a,b]+2^(y[n[a,b]+a+b]+1)
# x[n]+(y[n]/(N[n]))
# f[x[y]+m[n]+(a+b)]
我假设任何单词字符序列后跟一个左括号是一个函数名。
需要在循环中将()
临时替换为{}
而循环才能获得在函数参数内发生的分组括号。在完成所有功能替换f()
到f[]
之后,这是相反的。
答案 1 :(得分:3)
我建议在 word 字符之后匹配所有嵌套(...)
(甚至[a-zA-Z]
后跟\w*
匹配有效标识符),然后替换所有{{}在gsub块中包含(
和[
)
的内容。
]
在您的代码中:
strs = ['x(n)+(y(n)+1)*n', 'x(n(a,b),a,b)+2^(y(n(a,b)+a+b)+1)', 'x(n)+(y(n)/(N(n)))']
strs.each { |s|
puts s.gsub(/\b[a-zA-Z]\w*(\((?>[^()]|\g<1>)*\))/) { |m| m.gsub(/\(/,"[").gsub(/\)/,"]") }
}
结果:
fn=fn.gsub(/\b[a-zA-Z]\w*(\((?>[^()]|\g<1>)*\))/) { |m| m.gsub(/\(/,"[").gsub(/\)/,"]") }
正则表达式的解释:
x[n]+(y[n]+1)*n
x[n[a,b],a,b]+2^(y[n[a,b]+a+b]+1)
x[n]+(y[n]/(N[n]))
- 一个单词边界,后跟一个ASCII字母,后跟零个或多个单词字符(\b[a-zA-Z]\w*
)[a-zA-Z0-9_]
- 第1组匹配:
(\((?>[^()]|\g<1>)*\))
- 文字\(
(
- 与(?>[^()]|\g<1>)*
和(
以外的符号或整个第1组子模式匹配的原子组(子程序调用{{1}}))
- 结束文字\g<1>
答案 2 :(得分:-1)
单独使用经典正则表达式是不可能的。数学表达式可以嵌套在无限深度,但正则表达式使用有限状态机。 (无限深度的概念当然是一种抽象。因此,帮助你决定不同的复杂性是非常有价值的。在实践中,这意味着你需要的“正常”正则表达式取决于嵌套你的多少级别愿意支持它。它可以很快失控。)
你需要类似堆栈的东西来存储开括号的数量,所以当出现一个右括号时,你需要以某种方式将它与开括号匹配,以决定它是否需要替换。
<强> 编辑: 强> 我现在已经知道现代正则表达式(如ruby 2中)可以有递归子程序。有了这个,你应该能够解决嵌套问题。所以我的说法是不可能的不再是真的。