代码之家  ›  专栏  ›  技术社区  ›  GONeale

条件regex替换if值小于“nnnn”

  •  1
  • GONeale  · 技术社区  · 15 年前

    不确定使用正则表达式replace命令是否可以这样做,但是我有一个现有的regex replace,它将把数字的最后两位数转换为以句号为前缀的最后两位数。这是为了与一个以“2500”的形式发送货币值的系统连接,其中表示“25.00”美元。

    我现有的regex: (\d+)(\d{2})$
    替换语法为: $1.$2

    现在我有一个问题,如果一个值只是以“50”的形式发送,例如,它可能代表0.50,并且我的regex将失败,因为它在左边搜索1+数字,在字符串的末尾正好搜索两个数字。

    我如何才能涵盖所有这些情况,并让我的regex取代thully:

    2500 = 25.00
    500 = 5.00
    50 = 0.50
    5 = 0.05
    

    再次感谢 格雷厄姆

    更新:对于那些问为什么这不能是一个除法和字符串格式的工作是因为我必须避免自定义编程来实现这一点。理想情况下,它必须是一个在数据库中定义的regex“规则”以及其他regex定义,因为它正用于通用翻译系统。它将转换可能具有多种格式类型的输入数据,例如,通常将字段从“101”转换为“101A”,但在这种特殊情况下,需要为该数据类型添加值。

    第二个更新:我一直在考虑这个问题,因为我绑定到一个数据库,有人会看到比使用一个%WackyMoney%或在数据库字段中定义的其他“令牌”更好的方法,然后测试我们是否在代码中点击这个令牌来应用C字符串格式和除法?

    5 回复  |  直到 7 年前
        1
  •  2
  •   derobert    15 年前

    为什么要使用regexp?!用一个 单一的 regexp,但是您可以使用几个(一个用于3+数字大小写,一个用于2-数字大小写,一个用于1-数字大小写)。但是…

    我不知道确切的C语法,但我知道以下几点:

    sprintf('%0.2f', «var»/100.0)
    

    只要你的数字足够小,你的浮点类型的精度比0.01高,你就可以做你想做的事情。对于双打来说,这已经进入了四级。

    编辑1

    因为您需要regexps,所以可以使用三种语言(这里是Perl语法,但是…):

    s/^(\d+)(\d{2})$/$1.$2/;   # you already have this
    s/^(\d{2})$/0.$1/;         # obvious variant 1
    s/^(\d{1}$/0.0$1/;         # obvious variant 2
    

    其中只有一个匹配(变量1需要3个字符,变量2正好是2个字符,变量3正好是1个字符),因此如果可以附加多个regexp,则可以使用此选项。我可以在Perl中把所有这些都放到一个regexp中,但是我不知道您是否拥有完整的Perlregexp特性(我对此表示怀疑)。毕竟,Perl可以做到:

    s/^(\d+)$/sprintf('%0.2f', $1/100.0)/e
    

    但那相当欺骗。你的regexp引擎有类似的吗?或者你说这是数据库的东西;你能用SQL吗? CASE 有条件的?

        2
  •  3
  •   Chris R. Timmons    15 年前

    .NET regex可以使用匹配计算器将匹配转换为所需的内容:

    String result = Regex.Replace(
       "test 1 test 20 test 300 test 4000 test 50000",
       @"\d+",
       (match => (Double.Parse(match.Value) / 100).ToString("0.00")));
    

    结果是:

    test 0.01 test 0.20 test 3.00 test 40.00 test 500.00
    
        3
  •  2
  •   Blixt    15 年前

    正则表达式不能创建不存在的内容,因此不能添加不存在的零。所以答案是你不应该使用正则表达式。

    你最好的选择是 (Double.Parse(value) / 100).ToString("0.00") 或者一些这样的。


    因为您希望在数据库中定义一个通用规则集,所以我认为这里的错误是您将数字规则与字符串规则混合在一起。您应该使数据库支持不同类型的规则。

    我认为您应该有一个额外的列,指定该值是应该用数字修改还是作为字符串修改。如果应该对其进行数字修改,那么您可以让当前用于替换的列指定一个乘法器或一些类似的乘法器。

    如果你想做得更进一步,你可以有一个简单的公式评估器,它可以做如下的事情: x / 100 + " USD" . 已经有很多这样的东西可供.NET使用了,你自己也不难做一个简单的。

        4
  •  0
  •   Bernd    15 年前

    您是否有理由不将字符串转换为数字、除以100并转换回具有适当格式的字符串?

        5
  •  0
  •   goku_da_master    7 年前

    这可能无法准确回答OP的问题,但它可以为您提供一些关于如何根据条件利用匹配参数的想法。

    如果月份为12,下面的方法将交换日期的日和月部分。
    例子:

    string myStr = "14/3/2018";
    string newStr = MDYToDMY(myStr);
    Console.WriteLine(newStr); // prints "3/14/2018"
    
        static string MDYToDMY(string input)
        {
            try
            {
                return Regex.Replace(input,
                    "\\b(?<month>\\d{1,2})/(?<day>\\d{1,2})/(?<year>\\d{2,4})\\b",
                    (match => (int.Parse(match.Groups["month"].Value) > 12) 
                        ? $"{match.Groups["day"]}/{match.Groups["month"]}/{match.Groups["year"]}" 
                        : $"{match.Groups["month"]}/{match.Groups["day"]}/{match.Groups["year"]}"),
                    RegexOptions.None,
                    TimeSpan.FromMilliseconds(150));
            }
            catch (RegexMatchTimeoutException)
            {
                return input;
            }
        }