格式化带有破折号的字符串

16

我有一个从导入文件中提取的压缩字符串值。 我需要将其格式化为包裹号,该号码的格式如下:##-##-##-###-###。 因此,字符串“410151000640”应变为“41-01-51-000-640”。 我可以使用以下代码完成此操作:

String.Format("{0:##-##-##-###-###}", Convert.ToInt64("410151000640"));

然而,该字符串可能不全是数字;它可能会有一两个字母,因此将其转换为整数将失败。是否有一种方法可以对字符串执行此操作,以便每个字符(无论是数字还是字母)都可以正确地适配格式?

6个回答

38
Regex.Replace("410151000640", @"^(.{2})(.{2})(.{2})(.{3})(.{3})$", "$1-$2-$3-$4-$5");

或者稍微缩短一点的版本

Regex.Replace("410151000640", @"^(..)(..)(..)(...)(...)$", "$1-$2-$3-$4-$5");

非常好用!我将其提取到一个包装方法中,并添加了一些验证和错误处理。谢谢! - Kevin
我必须自己好好学习正则表达式。这是一个非常好的解决问题的方法。 - Øyvind Bråthen
1
如果有帮助的话,我喜欢使用http://www.regular-expressions.info/tutorial.html作为参考。他们还讨论了不同引擎提供的正则表达式不同风格。 - Yuriy Faktorovich
谢谢。我会去看看正则表达式,它看起来是一个很好的信息来源。 - Øyvind Bråthen

11

如果你知道“包裹号”始终遵循特定的规则,我建议你采用自己的格式化方法。

public static string FormatParcelNumber(string input)
{
  if(input.length != 12)
     throw new FormatException("Invalid parcel number. Must be 12 characters");

  return String.Format("{0}-{1}-{2}-{3}-{4}",
                input.Substring(0,2),
                input.Substring(2,2),
                input.Substring(4,2), 
                input.Substring(6,3), 
                input.Substring(9,3));
}

这个很好用。所以问题就在于是否使用正则表达式(我不是专家)或者不使用。 - Chris Patterson

3
这应该适用于您的情况:
string value = "410151000640";
for( int i = 2; i < value.Length; i+=3){
  value = value.Insert( i, "-");
}

现在value包含插入破折号的字符串。

编辑

我刚刚看到您没有在每个第二个数字之间添加破折号,因此这将需要进行一些微调(并且恐怕会变得有些笨拙)。

string value = "410151000640";
for( int i = 2; i < value.Length-1; i+=3){
  if( value.Count( c => c == '-') >= 3) i++;
  value = value.Insert( i, "-");
}

3
如果它是UI的一部分,您可以使用System.ComponentModel中的MaskedTextProvider
    MaskedTextProvider prov = new MaskedTextProvider("aa-aa-aa-aaa-aaa");
    prov.Set("41x151000a40");
    string result = prov.ToDisplayString();

你的掩码中的 'a' 应该改为 '&' 吗?'a' 表示字母数字字符,是可选的。它只接受 ASCII 字母 a-z 和 A-Z。http://msdn.microsoft.com/zh-cn/library/system.windows.forms.maskedtextbox.mask.aspx - Iain M Norman

1
这里有一个简单的扩展方法,具有一些实用性:
    public static string WithMask(this string s, string mask)
    {
        var slen = Math.Min(s.Length, mask.Length);
        var charArray = new char[mask.Length];
        var sPos = s.Length - 1;
        for (var i = mask.Length - 1; i >= 0 && sPos >= 0;)
            if (mask[i] == '#') charArray[i--] = s[sPos--];
            else
                charArray[i] = mask[i--];
        return new string(charArray);
    }

使用方法如下:

        var s = "276000017812008";
        var mask = "###-##-##-##-###-###";
        var dashedS = s.WithMask(mask);

你可以将它与任何字符串一起使用,除#以外的任何字符都将被插入到掩码中。掩码将从右向左工作。如果需要,您可以调整它以使其反向工作。
玩得开心。

0

如果我理解正确的话,您正在寻找一种从字符串中删除所有字母的函数,是吗?

我刚刚临时创建了一个,如果这恰好是您要找的内容,也许您可以将它转换为C#:

Dim str As String = "410151000vb640"
str = String.Format("{0:##-##-##-###-###}", Convert.ToInt64(MakeNumber(str)))


Public Function MakeNumber(ByVal stringInt As String) As String
    Dim sb As New System.Text.StringBuilder
    For i As Int32 = 0 To stringInt.Length - 1
        If Char.IsDigit(stringInt(i)) Then
            sb.Append(stringInt(i))
        End If
    Next
    Return sb.ToString
End Function

不,字母也包含在包裹号中,例如“410151000vb6”应变为“41-01-51-000-vb6”。 - Kevin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接