防止Javascript中SI前缀的正则表达式回溯

防止Javascript中SI前缀的正则表达式回溯,javascript,regex,Javascript,Regex,在Javascript中,我使用正则表达式捕获SI单位(和一些非SI单位),并使用乘法点正确格式化它们 例如:“Js”变成了“J”⋅s”和“mΩm”变为“mΩ⋅m“等 问题是,有些前缀也是国际单位制(例如“m”),所以我写的东西会错误地将“mΩ”转换为“m”⋅Ω” 更新正如@nhahdh指出的,问题在于前瞻回溯,因为它没有在Ω之后找到$unit,所以回溯并将m和Ω标识为$unit+$unit,而不是$prefix+$unit。在这种情况下,我需要防止回溯 ((?:p|n|m){0,1}(?:m|

在Javascript中,我使用正则表达式捕获SI单位(和一些非SI单位),并使用乘法点正确格式化它们

例如:“Js”变成了“J”⋅s”和“mΩm”变为“mΩ⋅m“等

问题是,有些前缀也是国际单位制(例如“m”),所以我写的东西会错误地将“mΩ”转换为“m”⋅Ω”

更新正如@nhahdh指出的,问题在于前瞻回溯,因为它没有在Ω之后找到
$unit
,所以回溯并将m和Ω标识为
$unit+$unit
,而不是
$prefix+$unit
。在这种情况下,我需要防止回溯

((?:p|n|m){0,1}(?:m|g|l|L|s|A))((?:p|n|m){0,1}(?:m|g|l|L|s|A))
编辑:现在更好地理解了您想要的内容,我认为这应该有效,前缀+单位(或仅前缀)的每一侧都保存在捕获组1和2中

(?:p|n|m) being the prefixes 


对于点的添加,您只需对结果进行筛选,并将点放在每个结果之后

我不认为您对每种情况都有唯一的解决方案

您希望将圆点放置在何处,例如mmΩ? 应该是mm吗⋅ Ω还是m⋅ mΩ? 我认为这两个答案都是正确的

编辑:

或者,如果我们看一个更荒谬的例子:(没有一个头脑正常的人会这样写)

mmmmol

我们可以通过以下方式进行拆分:

  • m⋅ M⋅ M⋅ 摩尔=m^3⋅ 摩尔
  • m⋅ M⋅ mmol=m^2⋅ 毫摩尔
  • m⋅ 嗯⋅ 摩尔
  • 嗯⋅ 毫摩尔
  • 嗯⋅ M⋅ 摩尔
因此,除非您指定一些假设,否则您可能无法完全按照您希望的方式获得每个边情况

编辑2:

防止这些不一致的一种方法是,当人们进入单元时,执行所提供的指南,并在出错时显示警告

编辑3:

如果你想表现出贪婪的行为,你就必须配上一种内氟林。否则最后一场比赛就不会被贪婪地对待

您还必须确保具有最长stringlength的单元位于匹配列表的前面。如果不这样做,它将匹配mol之前的m单位,并在那里退出,因此永远不会达到mol

请参阅jsfiddle以了解正在运行的代码

var $dot = "\u22c5";
var $minus = "\u2212";

var $prefix = "(?:\u00B5|c|d|G|k|m|M|n|p|T)";
var $si_unit = "(?:kat|mol|rad|\u00B0C|\u00B0F|Bq|cd|eV|Gy|Hz|lm|lx|Pa|sr|Sv|Wb|\u0025|\u03A9|A|C|F|g|H|J|K|l|L|m|N|s|S|T|V|W)";
var $power = "(?:[+" + $minus + "]?\\d+)";

var $unit = "("+ $prefix + "?"+ $si_unit + $power + "?)";

var $multiplied = $unit + "(" + $dot + $unit + ")*";
var $denominator = $multiplied + "(\/" + $multiplied + ")?";

var $corrections= [
    {
        // corrects dot products
        pattern: new RegExp( $unit + "(?=($|" + $unit + "))", "g" ),
        correction: "$1" + $dot
    }
    // more correction patterns later
];

$(document).ready(function() {


    var resultsElem = $("#results");

    addToResults(resultsElem, correct( "m" )); // m - CORRECT
    addToResults(resultsElem, correct( "m\u03A9" )); // mΩ - CORRECT, should be mΩ
    addToResults(resultsElem, correct( "\u03A9m" )); // Ω⋅m - CORRECT
    addToResults(resultsElem, correct( "m\u03A9m" )); // mΩ⋅m - CORRECT
    addToResults(resultsElem, correct( "mmmmol" )); // mm⋅mmol - CORRECT
});

function correct( $string ) {

    var $corrected = $string;
    $corrections.forEach( function( corrector ) {
        $corrected = $corrected.replace( corrector.pattern, corrector.correction );
    });

    //if you want greedy behaviour, you will have to match for the end of the line too.
    //The replace function will put a dot at the end too. Remove it if it's there.
    if($corrected.charAt($corrected.length -1 ) == $dot){
        $corrected = $corrected.substring(0,$corrected.length -1);
    }
    return $corrected;
}

function addToResults(elem, theResult){
    elem.append(theResult).append("<br>");
}
var$dot=“\u22c5”;
var$减=“\u2212”;
var$prefix=“(?:\u00B5 | c | d | G | k | m | n | p | T)”;
var$SiU单位:var$SiU U U U U U U U单位:“(?)var$SIU U U U U U U U U U盘基金会(124???)VAU U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U盘元元元元单位单位单位:::::::::::::卡卡卡卡蒂(卡托托托维维维维维维维维维维维维维维维维维维维维维维维维维维尼(Gy)GU U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U|W)“;
var$power=“(?:[+“+$减号+”]?\\d+”;
var$unit=“(“+$prefix+”?“+$si_单位+$power+”?)”;
变量$multipled=$unit+“(“+$dot+$unit+”)*”;
变量$分母=$乘以+“(\/“+$乘以+”)”;
var$修正=[
{
//修正点积
模式:新的RegExp($unit+”(?=($|“+$unit+”)),“g”),
更正:“$1”+$dot
}
//以后会有更多的修正模式
];
$(文档).ready(函数(){
var resultsElem=$(“#结果”);
addToResults(resultsElem,correct(“m”);//m-correct
addToResults(ResultLem,正确(“m\u03A9”);//mΩ-正确,应为mΩ
addToResults(结果元素,正确(“\u03A9m”);//Ω⋅m-正确
添加结果(结果元素,正确(“m\u03A9m”);//mΩ⋅m-正确
addToResults(resultsElem,correct(“mmmmol”);//mm⋅mmol-正确
});
函数正确($string){
var$corrected=$string;
$corrections.forEach(功能(校正器){
$corrected=$corrected.replace(corrector.pattern,corrector.correction);
});
//如果你想要贪婪的行为,那么你也必须在队伍的末尾进行匹配。
//replace函数也会在末尾添加一个点。如果有,请将其删除。
如果($corrected.charAt($corrected.length-1)=$dot){
$corrected=$corrected.substring(0,$corrected.length-1);
}
返回$corrected;
}
函数添加结果(元素、结果){
元素追加(theResult).append(
); }
问题在于前瞻性,它尝试匹配,但失败,而匹配回溯到m,前瞻性在m中找到Ω。我仍然有点困惑,基本上你希望任何前缀与任何SI单位混合都有一个Ω⋅ 在它之后出现?最重要的是,如果后面已经有一个点,不管在什么情况下都不创建点,那么你需要注意的因素就是(比如mΩ在一句话中,“thismΩhouse”应该变成“thismΩ⋅谢谢,但我看不出这和原来的有什么不同。我试图用
var$unit=“((?:“+$prefix+”)(?:“+$si_unit+”)“+$power+”)来适应我的代码但问题仍然存在。我是不是把它改错了?它应该是贪婪的,所以在你的例子中,mmmmol变成了mm⋅毫摩尔。
(?:m|g|l|L|s|A) being the units
var $dot = "\u22c5";
var $minus = "\u2212";

var $prefix = "(?:\u00B5|c|d|G|k|m|M|n|p|T)";
var $si_unit = "(?:kat|mol|rad|\u00B0C|\u00B0F|Bq|cd|eV|Gy|Hz|lm|lx|Pa|sr|Sv|Wb|\u0025|\u03A9|A|C|F|g|H|J|K|l|L|m|N|s|S|T|V|W)";
var $power = "(?:[+" + $minus + "]?\\d+)";

var $unit = "("+ $prefix + "?"+ $si_unit + $power + "?)";

var $multiplied = $unit + "(" + $dot + $unit + ")*";
var $denominator = $multiplied + "(\/" + $multiplied + ")?";

var $corrections= [
    {
        // corrects dot products
        pattern: new RegExp( $unit + "(?=($|" + $unit + "))", "g" ),
        correction: "$1" + $dot
    }
    // more correction patterns later
];

$(document).ready(function() {


    var resultsElem = $("#results");

    addToResults(resultsElem, correct( "m" )); // m - CORRECT
    addToResults(resultsElem, correct( "m\u03A9" )); // mΩ - CORRECT, should be mΩ
    addToResults(resultsElem, correct( "\u03A9m" )); // Ω⋅m - CORRECT
    addToResults(resultsElem, correct( "m\u03A9m" )); // mΩ⋅m - CORRECT
    addToResults(resultsElem, correct( "mmmmol" )); // mm⋅mmol - CORRECT
});

function correct( $string ) {

    var $corrected = $string;
    $corrections.forEach( function( corrector ) {
        $corrected = $corrected.replace( corrector.pattern, corrector.correction );
    });

    //if you want greedy behaviour, you will have to match for the end of the line too.
    //The replace function will put a dot at the end too. Remove it if it's there.
    if($corrected.charAt($corrected.length -1 ) == $dot){
        $corrected = $corrected.substring(0,$corrected.length -1);
    }
    return $corrected;
}

function addToResults(elem, theResult){
    elem.append(theResult).append("<br>");
}