如何使用正则表达式在逗号之间添加字符串和空值的引号

时间:2014-06-18 09:33:12

标签: regex preg-replace

也许是琐碎的问题,但我有问题。我有以下字符串:

,a1a,1a1,11,,aaa,,,a,84.34,"",ssd

我想通过使用正则表达式来实现以下效果:

"","a1a","1a1",11,"","aaa","","","a",84.34,"","ssd"

所以我希望逗号之间的所有内容都包含引号,除了整数和浮点数。如何使用正则表达式执行此操作?

2 个答案:

答案 0 :(得分:2)

(*跳过)(* F)魔术

demo中,查看底部的替换内容。

preg_replace这是一项很棒的任务,因为PCRE(PHP使用的正则表达式引擎)具有跳过某些内容的漂亮功能。

你可以通过这个可爱的正则表达式一步完成(参见demo):

((?<=^|,)\d+(?:\.\d+)?(?:(?=,)|$)(*SKIP)(*F)|(?<=^|,)[^,]*(?:(?=,)|$))

<强>解释

  • 外部括号将所有内容捕获到第1组。
  • 正则表达式分为两部分,| OR
  • 的每一边
  • 交替|的左侧使用\d+(?:\.\d+)?来匹配您不想要的这些浮点数和整数。我们使用lookbehind (?<=^|,)来确保后面有一个逗号(或字符串的开头),并使用(?:(?=,)|$)来检查后面的内容是逗号还是字符串的结尾。匹配后,我们故意失败,之后引擎跳到字符串中的下一个位置。
  • 右侧使用[^,]*匹配任何非逗号的内容,包括空的sring,我们知道它是正确的内容,因为它与左侧的表达式不匹配。我们再次使用外观来检查我们的位置。
  • 替换字符串'"\1"'将我们的匹配嵌入双引号中。

如何在代码中使用它

$regex = "~((?<=^|,)\d+(?:\.\d+)?(?:(?=,)|$)(*SKIP)(*F)|(?<=^|,)[^,]*(?:(?=,)|$))~";
$replaced = preg_replace($regex,'"\1"',$string);

答案 1 :(得分:0)

这是另一种变体:

$regex = '/(?<![^,])(?!"[^"]*")(?![-+]?[0-9]*\.?[0-9]+\b)[^,]*+(?![^,])/';
$result = preg_replace($regex, '"$0"', $subject);

以更易阅读的形式:

(?<![^,])
(?!
  "[^"]*"
  |
  [-+]?[0-9]*\.?[0-9]+\b
)
[^,]*+
(?![^,])

主要兴趣点是:

  • 负前瞻(?<![^,])以匹配前导分隔符(或不存在)。如果在此位置之前有字符,则可以将其读作,它不能是非逗号。并不总是可以使用这个习惯用法,但我喜欢它,因为它比较常见的(?<=^|,)感觉不那么笨拙,并且它不会浪费像(^|,)成语那样的捕获组。

  • 否定前瞻(?![^,])同样充当结束锚。

  • 在前瞻中,为防止它匹配已经引用的字段,我假设我不必担心转义引号。这些很容易处理,但首先你需要知道它是否使用反斜杠("a\"b\"c")或引号("a""b""c")来逃避它们。

  • 防止它匹配数字的负向前瞻使用来自RegexBuddy库的正则表达式,它是几个这样的正则表达式中最松散的。如果您需要更精确的东西,可以使用。