【问题标题】:RegEx to match string between delimiters or at the beginning or end正则表达式匹配分隔符之间或开头或结尾的字符串
【发布时间】:2014-05-14 04:54:16
【问题描述】:

我正在处理一个 CSV 文件,并且想要搜索和替换字符串,只要它在列中完全匹配。例如:

xxx,Apple,Green Apple,xxx,xxx
Apple,xxx,xxx,Apple,xxx
xxx,xxx,Fruit/Apple,xxx,Apple

如果“Apple”是列中的 EXACT 值,我想替换它(如果它包含在另一列的文本中,我不想替换)。我看不出如何用一个表达式来做到这一点(也许不可能?)。

想要的输出是:

xxx,GRAPE,Green Apple,xxx,xxx
GRAPE,xxx,xxx,GRAPE,xxx
xxx,xxx,Fruit/Apple,xxx,GRAPE

所以我想要的表达式是:匹配输入的开头或逗号,后跟所需的字符串,后跟逗号或输入的结尾。

您不能将 ^ 或 $ 放在字符类中,所以我尝试了 \A 和 \Z 但这不起作用。

([\A,])Apple([\Z,])

很遗憾,这不起作用。我可以用一个正则表达式来做到这一点吗?看起来这将是一个很常见的问题。

【问题讨论】:

    标签: regex language-agnostic


    【解决方案1】:

    这取决于您的语言,但如果您使用的语言支持环视,那么您将使用如下内容:

    (?<=,|^)Apple(?=,|$)
    

    替换为GRAPE

    否则,您将不得不放回逗号:

    (^|,)Apple(,|$)
    

    或者

    (\A|,)Apple(,|\Z)
    

    并替换为:

    \1GRAPE\2
    

    或者

    $1GRAPE$2
    

    取决于支持的内容。

    以上是原始的正则表达式(和替换)字符串。必要时逃跑。

    注意:后一种解决方案的缺点是它不适用于以下字符串:

    xxx,Apple,Apple,xxx,xxx
    

    因为第一个 Apple 后面的逗号被消耗掉了。如果遇到这种情况,您最多只能调用两次正则表达式替换。


    哦,我忘了提,你可以有一些“混合”,因为某些语言对后视有不同级别的支持(在下面的所有 ^\A$\Z、@ 987654334@ 和 $1 是可以互换的,所以我不会让它比现在更长):

    (?:(?<=,)|(?<=^))Apple(?=,|$)
    

    对于那些后视不能是可变宽度的,替换为GRAPE

    (^|,)Apple(?=,|$)
    

    上面是支持前瞻但不支持后视的地方。替换为\1Apple

    【讨论】:

    • “Apple,Apple”的好点子。您的环视解决方案正在捕获连续的列,但由于某种原因没有捕获最后一列。 regex101.com/r/eR6yH4 想法?
    • @KevinGwynn 哎呀,忘了把锚放在那里。这是第一个正则表达式和第二个正则表达式的混合。会解决的。
    【解决方案2】:

    如你所愿:

    • 查找内容:(^|,)(?:Apple)(,|$)
    • 替换为:$1GRAPE$2

    这适用于所有风格的 regex101。

    http://regex101.com/r/iP6dZ8

    【讨论】:

    • 不错!出于某种原因,我没有想到尝试 () 的。像您的 regex101 示例一样使用“/m”修饰符进行验证非常重要。
    • 不客气。很高兴它有帮助。注意@Jerry 对Apple,Apple 的评论。
    • 噢,伙计。在选择答案之前,请仔细考虑。从你身上拿走一个大的绿色复选标记真的很臭。我正要带它出去吃午饭。
    【解决方案3】:

    我想分享我最初的解决方法(在其他答案之前),尽管感觉更像是一种 hack。

    我只是在字符串前面加上一个逗号,然后再做更简单的:

    /,Apple,/,GRAPE,/g
    

    然后剪掉第一个和最后一个字符。

    PHP 看起来像:

    $line = substr(preg_replace($search, $replace, ','.$line.','), 1, -1);
    

    这仍然存在连续列的问题(例如“,Apple,Apple”)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-21
      • 2016-11-07
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 2015-04-27
      • 1970-01-01
      • 2018-01-28
      相关资源
      最近更新 更多