Javascript 如何解析和捕获任何度量单位

Javascript 如何解析和捕获任何度量单位,javascript,regex,language-agnostic,Javascript,Regex,Language Agnostic,在我的应用程序中,用户可以自定义测量单位,因此如果他们希望以分米而不是英寸或以整圈而不是度工作,他们可以。但是,我需要一种方法来解析包含多个值和单位的字符串,例如1'2“3/8。我在上面看到了一些正则表达式,但没有找到任何与英制的所有情况匹配的正则表达式,更不用说允许任何类型的单位了。我的目标是拥有尽可能多的允许输入框 因此,我的问题是:如何以最用户友好的方式从字符串中提取多个值单位对? 我提出了以下算法: 检查非法字符,并在需要时抛出错误 修剪前导和尾随空格 每次有一个非数字字符后跟一个数字

在我的应用程序中,用户可以自定义测量单位,因此如果他们希望以分米而不是英寸或以整圈而不是度工作,他们可以。但是,我需要一种方法来解析包含多个值和单位的字符串,例如
1'2“3/8
。我在上面看到了一些正则表达式,但没有找到任何与英制的所有情况匹配的正则表达式,更不用说允许任何类型的单位了。我的目标是拥有尽可能多的允许输入框

因此,我的问题是:如何以最用户友好的方式从字符串中提取多个值单位对?


我提出了以下算法:

  • 检查非法字符,并在需要时抛出错误
  • 修剪前导和尾随空格
  • 每次有一个非数字字符后跟一个数字字符时,将字符串拆分为多个部分,但用于标识小数和分数的.,/除外
  • 删除零件中的所有空格,检查字符是否误用(多个小数点或分数条),并将
    '
    替换为
    '
  • 每个零件的拆分值和单位字符串。如果零件没有单元:
    • 如果是第一个零件,请使用默认单位
    • 如果它是一个分数,就把它看作与前一部分相同的单位。 如果不是,根据前一部分的单位将其视为英寸、cm或mm。
    • 如果它不是第一部分,并且无法猜测单位,则抛出一个错误
  • 检查单位是否有意义,是否都是相同的系统(公制/英制),并遵循降序(英尺>英寸>分数或米>厘米>毫米>分数),如果没有,则抛出错误
  • 转换和求和所有部分,在过程中执行除法
  • 我想我可以使用字符串操作函数来完成大部分工作,但我觉得必须有一种更简单的方法来处理正则表达式


    我想出了一个正则表达式:
    “代码”部分以下以下以下代码:::(\d+)以下以下以下以下以下代码::(\d+)以下以下以下以下代码:::(\d+)以下以下以下以下以下代码:::(\d+;;;(d+(\124;???????)以及(d+)+++以下以下以下以下以下以下以下以下以下以下以下以下以下以下以下代码::::::::::((d+(\d++d+)+++++以及(((((//////\d+)上述上述上述上述上述,,,,,,,,,,,,,,///////\d+//////\d,,,,,,,,,,,/////\d?????????????????????????????????????????*)

    它只允许在末尾使用分数,并允许在值之间放置空格。不过,我从未使用过正则表达式捕获,所以我不太确定如何从混乱中提取值。我明天再做这件事

    我的目标是尽可能使用最宽松的输入框

    谨慎、更宽容并不总是意味着更直观。模棱两可的输入应该警告用户,而不是悄无声息地传递,因为这可能会导致他们在意识到自己的输入没有按预期解释之前犯下多个错误

    如何从字符串中提取多个值单位对?我想我可以使用字符串操作函数来完成大部分工作,但我觉得必须有一种更简单的方法来处理正则表达式

    正则表达式是一个强大的工具,特别是因为它们在许多编程语言中都可以工作,但请注意。当你拿着锤子的时候,一切看起来都像钉子。不要仅仅因为最近了解了正则表达式的工作原理就试图使用正则表达式来解决所有问题

    查看您编写的伪代码,您试图同时解决两个问题:拆分字符串(我们称之为标记化)和根据语法解释输入(我们称之为解析)。您应该首先尝试将输入拆分为令牌列表,或者可能是单位值对。一旦完成字符串操作,就可以开始理解这些对。关注点的分离将使您省去一件头痛的事,因此您的代码将更易于维护

    不过,我从未使用过正则表达式捕获,所以我不太确定如何从混乱中提取值

    如果正则表达式具有全局(
    g
    )标志,则可以使用它在同一字符串中查找多个匹配项。如果您有一个可以找到单个单位值对的正则表达式,那么这将非常有用。在JavaScript中,您可以使用
    string.match(regex)
    检索匹配列表。但是,该函数忽略全局正则表达式上的捕获组

    如果要使用捕获组,需要在循环内调用
    regex.exec(string)
    。对于每个成功的匹配,
    exec
    函数将返回一个数组,其中item
    0
    是整个匹配,items
    1
    及以后是捕获的组

    例如,
    /(\d+)([a-z]+)/g
    将查找后跟空格和单词的整数。如果您连续调用
    regex.exec(“1小时30分钟”)
    您将得到:

    • [“1小时”、“1小时”、“1小时”]
    • [“30分钟”,“30”,“分钟”]
    • null
    连续调用是这样工作的,因为regex对象保留一个内部游标,您可以使用
    regex.lastIndex
    获取或设置该游标。在使用不同的输入再次使用正则表达式之前,应该将其设置回0

    您一直在使用括号分隔OR子句,如
    a | b
    ,并将量词应用于字符序列,如
    (abc)+
    。如果您想在不创建捕获组的情况下执行此操作,可以使用
    (?:)
    。这称为非捕获组。它的作用与正则表达式中的普通圆括号相同,但其内部的内容不会在返回的数组中创建条目

    有没有更好的办法

    这个答案的前一个版本以一个正则表达式结束,这个正则表达式甚至比问题中发布的正则表达式更令人费解,因为我当时不太清楚,但今天这将是我的建议。它是一个正则表达式,一次只能从输入字符串中提取一个标记

    / (\s+)                             // 1 whitespace
    | (\d+)\/(\d+)                      // 2,3 fraction
    | (\d*)([.,])(\d+)                  // 4,5,6 decimal
    | (\d+)                             // 7 integer
    | (km|cm|mm|m|ft|in|pi|po|'|")      // 8 unit
    /gi
    
    很抱歉,语法突出显示很奇怪。我使用空格使其更具可读性,但格式正确:

    /(\s+)|(\d+)\/(\d+)|(\d*)([.,])(\d+)|(\d+)|(km|cm|mm|m|ft|in|pi|po|'|")/gi