如何在每个数字处使用正则表达式拆分字符串

时间:2019-02-12 13:59:07

标签: regex ruby

我试图更改计算器程序的输入以删除所有空白并更正格式。

如果格式如下:

2 + 3 * ( 2 + 2 )

我采用此值,将其在每个空间处拆分为一个数组,将每个数字都转换为浮点数,然后我的程序可以在符合PEMDAS的同时递归解决问题。但是,如果用户要进来并在以下位置进行重击:

2+3*(2+2)

它将破裂。我可以将其拆分为每个数字,然后如果用户输入

22+33*(22+22)

坏了。

所以我的想法是删除所有空格,然后使用正则表达式查找所有数字,运算符,花括号等,然后像以前一样将它们拆分为数组。

我想要的结果是:

["2.0", "+", "3.0", "*", "(", "2.0", "+", "2.0", ")"]

我有以下建议,这不起作用

better_format = ss.scan(/\d*\.\d*|\+|\-|\*|\%\/|\(\)/) => ["2.0", "+", "3.0", "*", "", "2.0", "+", "2.0", "", ""]

我需要一些输入。据我了解,我的表情是在寻找

  • 任意位数,后跟一个句点,后跟任意位数
  • 以下任何一个字符'+,-,*,/,%,(,)'

3 个答案:

答案 0 :(得分:1)

您可以使用

s.scan(/\d*\.?\d+|[-+\/*%()]/)

请参见regex demo

或者,匹配数字以外的任何类型的非空白:

s.scan(/\d*\.?\d+|[^\d\s]/)
                  ^^^^^^^

请参见Ruby demo

详细信息

  • \d*\.?\d+-0或更多数字,可选的.然后是1+数字
  • |-或
  • [-+\/*%()]-a -+/*%(或{{1} }
  • )-除空格和数字外的任何字符

答案 1 :(得分:1)

整数

除了使用#scan过滤掉想要的内容之外,您还可以使用#split过滤掉不需要的内容。

'2 + 3 * ( 2 + 2 )'.split(/\s+|\b|(?=\W)/)
#=> ["2", "+", "3", "*", "(", "2", "+", "2", ")"]

'22+33*(22+22)'.split(/\s+|\b|(?=\W)/)
#=> ["22", "+", "33", "*", "(", "22", "+", "22", ")"]

此正则表达式拆分于:

  • 例如,给定\s+的空格(22 +
  • 例如给出\b时的单词边界(22+)。
  • 例如,当给出(?=\W)时,字符后跟非单词字符(*()。

浮动

以上内容适用于整数,但不适用于浮点数。为了正确解析浮点数,我们需要自己编写\b\b等于(?<=\w)(?!\w)|(?<!\w)(?=\w),因此大量使用lookarounds。如果我们仅将其应用于小数点和点,则将导致(?<=[\d.])(?![\d.])|(?<![\d.])(?=[\d.])

产生以下正则表达式:

float_boundary = /(?<=[\d.])(?![\d.])|(?<![\d.])(?=[\d.])/
non_float_boundary = /(?<![\d.])(?![\d.])/
regex = /\s+|#{float_boundary}|#{non_float_boundary}/

'22.22+33*(22.34+22.1)'.split(/\s+|\b|(?=\W)/)
#=> ["22", ".", "22", "+", "33", "*", "(", "22", ".", "34", "+", "22", ".", "1", ")"]

'22.22+33*(22.34+22.1)'.split(regex)
#=> ["22.22", "+", "33", "*", "(", "22.34", "+", "22.1", ")"]

答案 2 :(得分:0)

R = /
    (?:       # begin a non-capture group
      (?<=    # begin a positive lookbehind
        \d    # match a digit
        [ ]?  # optionally match a space
      )       # end positive lookbehind
      -       # match a minus sign
    )         # end non-capture group
    |         # or
    -?        # optionally match a minus sign
    \d+       # match one or more digits           
    (?:       # begin a non-capture group
      \.      # match a period 
      \d+     # match one or more digits
    )         # end non-capture group
    ?         # optionally match non-capture group above
    |         # or
    \S        # match a non-whitespace character
    /x        # free-spacing regex definition mode

def doit(str)
  str.scan(R)
end

doit "2 + 3 * ( 2 + 2 )"
  #=> ["2", "+", "3", "*", "(", "2", "+", "2", ")"] 
doit "2+3*(2+2)"
  #=> ["2", "+", "3", "*", "(", "2", "+", "2", ")"] 
doit "22+33*(22+22)"
  #=> ["22", "+", "33", "*", "(", "22", "+", "22", ")"] 
doit "(22+33)!*(22-12)"
  #=> ["(", "22", "+", "33", ")", "!", "*", "(", "22",
  #    "-", "12", ")"] 
doit "(22-33)*(22/-12)"
  #=> ["(", "22", "-", "33", ")", "*", "(", "22", "/",
  #    "-12", ")"] 
doit "(22+33.4)*(22/-12.3)"
  #=> ["(", "22", "+", "33.4", ")", "*", "(", "22", "/",
  #    "-12.3", ")"] 
doit "2-1"
  #=> ["2", "-", "1"] 
doit ".2"
  #=> [".", "2"] 

常规表达通常如下。

/(?:(?<=\d )-)|-?\d+(?:\.\d+)?|\S/

请注意,使用自由行距模式时,必须在字符类([ ])中保护正则表达式中的空格,因为在计算表达式之前会删除空格。