2012-11-09 259 views
3

在每次从字母数字到数字的变化之后,是否可以帮助我分割一个字符串(或者首选,如果可能,请在每个“拆分”场合放置一个空格),反之亦然?正则表达式:拆分字符串字母数字/数字

所以像D2c1 22这样的字符串应该看起来像D 2 c 1 22。最好的办法是对从字母数字到数字的每一个变化都留下一个空白。

+1

我可以帮你,但你不能做到这一点。 –

+1

有点相关的是这个关于自然排序包含数字和非数字序列混合的字符串的问题。其中的一些查询可能对您有用。 http://stackoverflow.com/questions/12965463/humanized-or-natural-number-sorting-of-mixed-word-and-number-strings –

回答

2

下面是PostgreSQL的测试的方法和验证工作。这有点折磨,所以表演可能会......有趣。

CREATE AGGREGATE array_cat_agg (
    BASETYPE = anyarray, 
    SFUNC = array_cat, 
    STYPE = anyarray 
); 
SELECT array_to_string(array_cat_agg(a), ' ') 
FROM regexp_matches('234kjh23ljkgh34klj2345klj', '(\D*)(\d*)', 'g') x(a); 

我们需要array_cat_agg因为经常array_agg不能阵列的总阵列。

或者,@ davidrac的做法的一种形式,将与PostgreSQL的工作,可能会表现更好显著(虽然我还没有测试)是:

SELECT regexp_replace(
    regexp_replace(
    '234kjh23ljkgh34klj2345klj', '(\d)(\D)', '\1 \2', 'g' 
), '(\D)(\d)', '\1 \2', 'g'); 

这是执行在两次传球替换。首先它插入一系列数字结束和一系列非数字开始的空间。然后在另一个通行证中插入一系列非数字结尾和一系列数字开始的空格。

更新:下面是一个改进配方:

SELECT trim(regexp_replace('234kjh23ljkgh34klj2345klj', '(?!\d)(\D+)|(?!\D)(\d+)', '\1\2 ', 'g')); 
+1

@davidrac验证您的第二个配方与Pg配合使用。上面的Pg以及更早的(更丑陋的)实现。为你的答案+1了。 –

+0

谢谢。但我胆量完全相同的测试字符串(234kjh23ljkgh34klj2345klj)结果当我尝试上述的SQL与双regexp_replace – calimero

+1

@calimero你可以在'standard_conforming_strings'更改之前使用旧版本的PostgreSQL(9.0或更早版本)吗?尝试'SET standard_conforming_strings = on;'然后再次测试。 (这就是为什么你总是在提问中提到你的PostgreSQL版本的原因)。如果它适用于'standard_conforming_strings',那么(a)升级PostgreSQL并(b)参见http://www.postgresql.org/docs/current/static/runtime-config-compatible.html#GUC-STANDARD-CONFORMING- STRINGS用于如何在不升级PostgreSQL的情况下使查询生效。基本上,而不是''''使用'E'\\'';双反斜杠并使用'E''。 –

3

您可以使用此正则表达式找到的地方则切换:

(?<=\d)(?=\D)|(?<=\D)(?=\d) 

这样:

"234kjh23ljkgh34klj2345klj".gsub(/(?<=\d)(?=\D)|(?<=\D)(?=\d)/, " ") 
=> "234 kjh 23 ljkgh 34 klj 2345 klj" 

编辑:没有零长度向前看和向后看:

"234kjh23ljkgh34klj2345klj".gsub(/(\d)(\D)/, "#{$1} #{$2}").gsub(/(\D)(\d)/, "#{$2} #{$1}") 
=> "23 jk 5 jkgk 5 lk 534 lj" 
+0

Pg(至少9.2)似乎不明白,正则表达式,不幸的是, 。 (?= \ D)(?<= \ D)(?)?????选择regexp_replace('234kjh23ljkgh34klj2345klj','(?<= \ d)= \ d)','','g');' '错误:无效正则表达式:量词操作数无效。请参阅http://sqlfiddle.com/#!12/d41d8/148 –

+0

它可能无法处理零长度的向前看和向后看。在这种情况下,你可以使用类似这种方法(这是ruby语法,所以你必须调整):“234kjh23ljkgh34klj2345klj”.gsub(/(\ d)(\ D)/,“#{$ 1}#{$ 2 }“)。gsub(/(\ D)(\ d)/,”#{$ 2}#{$ 1}“) =>”23 jk 5 jkgk 5 lk 534 lj“ – davidrac

+2

pg中的lookahead语法doc):(?= re)\t在子字符串匹配重新开始的任何点上的正向预测匹配 (?!re)\t负向预测匹配在没有子字符串匹配重新开始的任何点上(仅限ARE) – davidrac

1

Best way from would be to put a blank at every change from alpha-numeric to numeric.

它并不难做到:

$ echo "D2c1 22" | sed 's|\([a-ZA-Z]\)\([0-9]\)|\1 \2|g;s|\([0-9]\)\([a-ZA-Z]\)|\1 \2|g' 
D 2 c 1 22 

在这里,我用sed和正则表达式,因为你没有提到你使用的语言。主要思想是使用2个正则表达式替换alpha与数字和数字与alpha到第一个字符,空格和第二个字符。

+0

非常感谢快速的共鸣。我想在postgresql中完成它。 – calimero

1

可以匹配使用正则表达式

(?<=[a-z])(?=[0-9])|(?<=[0-9])(?=[a-z]) 

,并用空格代替它。

See it in Perl

+0

作为@ davidrac的解决方案,似乎Pg的正则表达式引擎无法应对该问题。请参阅http://sqlfiddle.com/#!12/d41d8/148 –

+0

通常更好的方法是使用'\ d'和'\ D',这样您就可以处理任何数字和非数字序列,而不仅仅是小写字母数字。 –

相关问题