正则表达式填充零

时间:2015-02-17 04:55:52

标签: sql regex postgresql natural-sort

我想在桌面上输入一系列字符串。 例如

Chapter 1 
Chapter 2 
Chapter 11 
Chapter 12

要正确订购,我需要用零填充它们。

Chapter 001 
Chapter 002 
Chapter 011 
Chapter 012

也许我可以使用正则表达式在零中使用 regexp_replace() pad。

  regexp_replace(chapters.name,'(\d+)\D*','0\1') as name

此解决方案无效。我想也许我可以弄清楚反向引用的长度并使用该数字填充我需要的东西:

  regexp_replace(chapters.name,'(\d+)\D*',lpad('\l',3-length('\1'),'0') as name

\1中的length()始终返回2,即使我注意到在某些postgres函数\1中使用\1将{{1}}转换为实际捕获的数据。

如何使用Postgres字符串函数和Postgres正则表达式填充零?

1 个答案:

答案 0 :(得分:5)

问题

你的第二次尝试是两个误解的受害者:

  • lpad()rpad()的第二个参数是结果总长度,而不是添加的字符数。< / p>

  • 您将regexp_replace()的范围与lpad()的范围混淆。 lpad()首先执行,\l\1lpad()没有特殊含义。

解决方案

这是“自然排序”的问题。相关回答:

正如那里所建议的那样,最好的解决方案是存储标准化数据。如果前导'Chapter'实际上是所有值中的不可变字符串,请不要存储它,只将数字部分存储为integer

如果您的示例值是准确的,我们可以忽略前导常量文本,只按尾随数字排序。比任何重新格式化字符串的尝试要快得多:

SELECT *
FROM   chapters
ORDER  BY split_part(name, ' ', 2)::int

如果您确实需要零填充字符串,并且前导文本可能会有所不同:

SELECT split_part(name, ' ', 1) || ' '
    || lpad(split_part(name, ' ', 2), 3,  '0')
FROM   chapters
ORDER  BY 1;

SQL Fiddle.

两个函数调用加上连接,但仍然比regexp_replace()快。正则表达式相对昂贵 lpad()的更多示例: