【问题标题】:Regexes: How to use the length of a match in the replacement expression正则表达式:如何在替换表达式中使用匹配的长度
【发布时间】:2013-06-13 13:57:26
【问题描述】:

我正在尝试编写一个正则表达式,它将一些样板 SQL 代码重新格式化为一个更简洁的版本。这是一个例子。

我有:

SELECT
    [Person].[Name]
    [Person].[Address],
    [Sales].[TotalAmount]

我想要:

SELECT
    [Name]        = [Person].[Name],
    [Address]     = [Person].[Address],
    [TotalAmount] = [Sales].[TotalAmount]

我可以写一个表达式把字段名移到赋值语句的左边,没问题。棘手的部分是正确的间距——有没有办法在替换中使用匹配的长度?另外,要使用最长匹配的长度吗?这样 "[Name]" 后跟 length("TotalAmount") - length("Name") = 7 个空格,"[Address]" 后跟 length("TotalAmount") - length("Address") = 4 个空格,等等?

我不确定这对于正则表达式是否可行,但我想我会把它扔在那里,希望有一些正则表达式大师知道如何做到这一点。

【问题讨论】:

  • 什么语言/环境下的正则表达式?
  • 对不起,SQL Server Management Studio,我相信它使用与 Visual Studio 相同的方言。
  • 是的,您必须在工具中进行一些杂耍。单独的正则表达式无法让您做到这一点(您已经达到了正则表达式的确切限制 - 状态“计数”)。
  • 这就是我开始的想法,是的......我不会编写解析器来清理我的 SQL。

标签: sql regex


【解决方案1】:

关闭语言,但仍会发布。

在 PHP 中有preg_replace_callback(),它可以让你用正则表达式匹配一个字符串,然后用 PHP 处理它。所以这里有一个完整的PHP解决方案,注意你需要PHP 5.3+:

$sql = 'SELECT
    [Person].[Name]
    [Person].[Address],
    [Sales].[TotalAmount]';

preg_match_all('#\[[^]]+\]\.(\[[^]]+\])#', $sql, $found); // Match
$max = max(array_map('strlen', $found[1])); // Find max length

$new = preg_replace_callback('#\[[^]]+\]\.(\[[^]]+\])#', function($m)use($max){
    $string = $m[1].str_repeat(' ',$max - strlen($m[1])).' = '.$m[0]; // Constructing
    return($string);
}, $sql);
echo $new;

输出:

SELECT
    [Name]        = [Person].[Name]
    [Address]     = [Person].[Address],
    [TotalAmount] = [Sales].[TotalAmount]

Online demo

【讨论】:

  • 这是一个很好的答案。为了清理我的 SQL 代码,我可能不得不将其放入 PHP 脚本中。谢谢!
猜你喜欢
  • 1970-01-01
  • 2012-05-16
  • 2015-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-06
  • 2021-04-10
  • 1970-01-01
相关资源
最近更新 更多