我有一个CLI计算器,并且正在添加平方根函数。我有这个正则表达式解析用户输入:
string.scan(/\d*\.?\d+\^?|[-+\/*%()]|sqrt\(\d*\.?\d+\)/)
它可以按预期使用这些输入:
calc -o "sqrt(9)" #=> ["sqrt(9)"]
calc -o "sqrt(9) + sqrt(9)" #=> ["sqrt(9)", "+", "sqrt(9)"]
但是,我的正则表达式没有考虑嵌套sqrt。这样,
calc -0 "sqrt(6+3)"
我想要输出:
["sqrt(6+3)"]
因为当程序在搜索时发现sqrt
时,它将简单地将scan
方法与正则表达式一起递归应用,直到它进入最深层的嵌套公式并返回原位。但是我得到了:
["(", "6", "+", "3", ")"]
我尝试捕获除sqrt括号内的所有内容,但也捕获所有其他括号内的所有内容。因此,我在捕获sqrt(9)
和sqrt(6+3)
时遇到麻烦,而又没有一个相互干扰。
非常感谢任何指导。
更新:因此,从提供的答案开始,也许我需要更多地解释我的程序,以便您了解发生了什么。
说我有输入2 * (3 + 5)
,它将被解释为以下数组:
["2", "*", "(", "3", "+", "5", ")"]
因此程序符合PEDMAS,因此将首先查找括号,在这种情况下它将找到括号。一个基本的循环基本上是这样的:
function find_backets
start_i, end_i
for i in array do
if i == "("
start_i = index
find_brackets
end
if i == ")"
end_i = index
# end of nest
end
end
然后,我可以将数组中的开始和结束位置传递给一个函数,该函数将在每个嵌套操作上进行迭代。因此,上面的代码可以很好地解释这一点:
calc -o "2 * (6 + (2 * 2))"
#=> ["2", "*", "(", "6", "+", "(", "2", "*", "2", ")", ")"]
我的想法是,当遇到sqrt函数时,它将仅重用用于用户输入的同一个正则表达式,并创建一个全新的数组并对其执行上面的操作。然后,一旦完成,我将索引0放置在sqrt过去的位置。
编辑:是的,实际上没有提到,我基本上是捕获了整个sqrt。 sqrt(5+5*(6/2+sqrt(9))
更新:我想我已经找到了解决方法
因此,我做了一些阅读工作,以了解* + ?
的工作原理,而且效果还好一些,我认为(至少到目前为止)这是可行的
string.scan(/\d*\.?\d+\^?|[-+\/*%()^]|sqrt\(.+?\)+|pi/)
calc -o "sqrt(9)" #=> ["sqrt(9)"]
calc -o "sqrt(3+6)" #=> ["sqrt(3+6)"]
calc -o "sqrt(9) + sqrt(9)" #=> ["sqrt(9)", "+", "sqrt(9)"]
calc -o "sqrt(9) + 2" #=> ["sqrt(9)", "+", "2"]
稍后会更新
答案 0 :(得分:0)
有一些困扰您的问题:
首先,正则表达式不处理递归搜索,因此您将无法找到匹配的括号。如果您希望能够在sqrt()
内接受括号表达式,则需要attack it from a different angle(那里的答案指向this algorithm)。
如果只希望在sqrt()
内部匹配简单表达式,那么下一个问题是:在sqrt
子表达式中,您可以选择匹配文字句点字符{{1 }}之间的数字,但您不允许任何运算符。您可以通过向运算符添加匹配项以及该子表达式中的可选第二个浮点数来直接解决此问题。在以下示例中,我将加法包在non-capturing group \.?
中,并使用(?:_expression_)
将其匹配0次或更多次。
*
变为sqrt\(\d*\.?\d+\)
最后,您很可能希望先评估sqrt\(\d*\.?\d+(?: *?[-+\/*%]? *?\d*\.?\d*)*\)
的内容,然后再评估sqrt()
本身。为此,您需要使用捕获组。有几种方法可以解决此问题,但是一种方法是将整个表达式用不转义的括号括起来(捕获组1),然后sqrt()
的内容也应该用不转义的括号括起来(捕获组2)
sqrt()
扫描结果将是捕获组阵列的阵列。在/(\d*\.?\d+\^?|[-+\/*%()]|sqrt\((\d*\.?\d+(?: *?[-+\/*%]? *?\d*\.?\d*)*)\))/
上运行它会返回"sqrt(9) + sqrt(9)"
,因此无论何时捕获组2都不是[["sqrt(9)", "9"], ["+", nil], ["sqrt(9)", "9"]]
,它都包含nil
的内容。
您可以在Regexr上看到此正则表达式的作用