在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和Ω标识为{{ 1}}而不是$unit + $unit
。在这种情况下,我需要防止回溯。
答案 0 :(得分:2)
我认为每个案例都没有独特的解决方案。
你想把点放在哪里例如mmΩ? 它应该是mm⋅Ω还是m·mΩ? 在我看来,这两个答案都是有效的。
修改强>
或者,如果我们看一个更荒谬的例子:(虽然他们心智正常的人会像这样写出来)
mmmmol
我们可以通过以下方式分割它:
因此,除非您指定一些假设,否则您可能无法完全按照您希望的方式获得每个边缘情况。
编辑2:
防止这些不一致的一种方法是在人们进入单位时强制执行here所示的指导方针,并在他们犯错时显示警告。
编辑3:
如果你想要贪婪的行为,你必须匹配endOfLine。否则,最后一场比赛不会以贪婪的方式对待。
您还必须确保具有最长stringlength的单位位于匹配列表的前面。如果你不这样做,它会在 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>");
}
答案 1 :(得分:1)
((?: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
和
(?:m|g|l|L|s|A) being the units
对于添加点,您只需在结果中进行迭代,并在每个结果后放置点