【问题标题】:How to split a user-generated string which may contain the delimitter?如何拆分可能包含分隔符的用户生成的字符串?
【发布时间】:2009-09-19 16:47:38
【问题描述】:

我想 String.Split() 使用逗号作为分隔符的以下字符串:

John,Smith,123 Main Street,212-555-1212

以上内容由用户输入。如果他们在地址中输入逗号,则生成的字符串会导致 String.Split() 出现问题,因为您现在有 5 个字段而不是 4 个:

John,Smith,123 Main Street, Apt 101,212-555-1212

我可以在所有用户输入上使用 String.Replace() 将逗号替换为其他内容,然后再次使用 String.Replace() 将内容转换回逗号:

value = value.Replace(",", "*");  

但是,如果用户碰巧在他们的输入中使用了占位符分隔符“*”,这仍然会被愚弄。然后你会得到额外的逗号,结果中没有星号。

我在网上看到了处理转义分隔符的解决方案,但我还没有找到解决这种看似常见情况的解决方案。我错过了什么?

编辑:这称为delimitter collision

【问题讨论】:

  • 您的问题与转义分隔符解决的问题有何不同? IE。为什么不转义分隔符?
  • 您说您可以在所有用户输入上替换逗号,这听起来就像此时值是分开的。为什么然后将它们塞到一个字符串中?

标签: c# csv


【解决方案1】:

这是一种常见的情况——您有一些任意的字符串值,您想将它们组合成一个结构,该结构本身就是一个字符串,但不允许这些值干扰它们周围结构中的分隔符。

您有多种选择:

  1. 输入限制:如果您的方案可以接受,最简单的解决方案是限制在值中使用分隔符。在您的具体情况下,这意味着不允许使用逗号。
  2. 编码:如果输入限制不合适,下一个最简单的选择是对整个输入值进行编码。选择在其可能的输出范围内没有分隔符的编码(例如,Base64 在其编码输出中没有逗号)
  3. 转义分隔符:一个稍微复杂的选项是想出一个转义分隔符的约定。如果您正在使用诸如 CSV 之类的主流内容,则转义问题可能已经解决,并且您可以使用一个标准库。如果没有,那就需要考虑一下,想出一个完整的转义系统,并实施它。

如果您可以灵活地不使用 CSV 来表示您的数据,这将打开许多其他选项。 (例如,考虑参数化 SQL 查询通过将参数值与查询字符串分开存储来回避输入转义的复杂性的方式。)

【讨论】:

    【解决方案2】:

    这对您来说可能不是一个选项,但是使用一个非常不常见的字符(例如竖线 |)作为您的分隔符并且不允许在第一个实例中输入此字符不是更容易吗?

    【讨论】:

    • 是的,这就是我的原始代码所做的。它工作正常,但我正在寻找更通用的解决方案。
    • 公平点 Bob 不确定您是否尝试过原始问题中的简单解决方案。也喜欢base64的答案。
    【解决方案3】:

    如果是CSV,地址应该用引号括起来。 CSV 解析器广泛可用,在解析文本时会考虑到这一点。

    John,Smith,"123 Main Street, Apt. 6",212-555-1212
    

    【讨论】:

      【解决方案4】:

      一个万无一失的解决方案是将用户输入转换为 base64,然后用逗号分隔。这意味着您必须在解析后转换回来。

      【讨论】:

      • 优秀。非常感谢。这是我永远不会想到的。
      【解决方案5】:

      您可以尝试在每个用户输入周围加上引号或其他一些开始和结束分隔符,并忽略一组引号之间的任何特殊字符。

      这实际上归结为清理用户输入的情况。您应该只允许用户输入中需要的字符,并拒绝/删除用户的无效输入。这样您就可以使用星号分隔符。

      最好的解决方案是定义有效字符,并以某种方式拒绝无效字符,然后使用无效字符(由于它们被“禁止”而不会出现在输入中)作为分隔符

      【讨论】:

      • 为什么投反对票?尤其是当我开始建议当前最受好评的答案时,同时试图提出更好的解决方案?
      【解决方案6】:

      不允许用户输入您用作分隔符的字符。我个人觉得这是最好的方法。

      【讨论】:

        【解决方案7】:

        有趣的解决方案(如果地址是唯一带逗号的字段,则有效):

        用逗号分割字符串。前两部分是姓名和姓氏;最后一块是电话——把它们拿走。用昏迷组合其余部分 - 那将是地址;)

        【讨论】:

          【解决方案8】:

          从某种意义上说,用户已经“转义”逗号和空格。

          所以,试试这个:

          string[] values = RegEx.Split(value, ",(?![ ])");
          

          如果用户不输入空格,他们仍然可以打破这一点,并且有一种更简单的方法(使用标准 CSV 方法来引用包含逗号的值),但这对于您的用例来说是有用的已经提出了。

          另一种解决方案:提供“地址 2”字段,这是传统上诸如公寓号码之类的内容。用户仍然可以在懒惰的情况下破坏它,尽管他们实际上会破坏地址2之后的字段

          【讨论】:

            【解决方案9】:

            礼貌地提醒您的用户,美国和加拿大格式正确的街道地址不应该包含任何标点符号,也许?

            如果没有启发式逻辑,自动将损坏的数据转换为有用数据的过程是不平凡的。您可以尝试通过调用第三方地址格式库来应用 USPS 格式规则来外包解析。

            即使是 USPS 也要求用户执行大部分工作,方法是将地址的组成部分输入到其地址“规范化器”页面 (http://zip4.usps.com/zip4/welcome.jsp) 上的不同字段中。

            【讨论】:

            • 我想支持美国和加拿大以外的地址。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多