gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:00:43 27 4
gpt4 key购买 nike

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

例如:“Js”变为“J⋅s”,“mΩm”变为“mΩ⋅m”等

问题是,有些前缀也是 SI 单位(例如“m”),所以我写的内容会错误地将“mΩ”转换为“m⋅Ω”。

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

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

function correct( $string ) {

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

correct( "m" ); // m - CORRECT
correct( "mΩ" ); // m⋅Ω - INCORRECT, should be mΩ
correct( "Ωm" ); // Ω⋅m - CORRECT
correct( "mΩm" ); // mΩ⋅m - CORRECT

更新 正如@nhahtdh 指出的那样,问题在于前瞻回溯,因为它在 Ω 之后找不到 $unit,因此回溯并识别 m 和Ω 作为 $unit + $unit 而不是 $prefix + $unit。在这种情况下,我需要防止回溯。

最佳答案

我不认为您对每种情况都有独特的解决方案。

你想把点放在什么地方,例如 mmΩ?应该是 mm ⋅ Ω 还是 m ⋅ mΩ?我认为这两个答案都是有效的。

编辑:

或者,如果我们看一个更可笑的例子:(虽然头脑正常的人不会这样写)

嗯嗯

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

  • m ⋅ m ⋅ m ⋅ mol = m^3 ⋅ mol
  • m ⋅ m ⋅ mmol = m^2 ⋅ mmol
  • 米·毫米·摩尔
  • mm ⋅ mmol
  • mm ⋅ m ⋅ mol

因此,除非您指定一些假设,否则您可能不会完全按照您想要的方式获得每个边缘情况。

编辑 2:

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

编辑 3:

如果你想要贪婪的行为,你将不得不匹配一个 endOfLine。否则最后一场比赛不会以贪婪的方式对待。

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

参见 this用于实际代码的 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>");
}

关于javascript - 防止 Javascript 中 SI 前缀的正则表达式回溯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26423373/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com