【问题标题】:Insert missing commas in C source在 C 源代码中插入缺少的逗号
【发布时间】:2018-02-28 13:56:17
【问题描述】:

我有一个 perl 脚本(使用 -p 标志)对损坏的 C 源文件执行一些更正。这是脚本的一部分:

sub remove_sp {
    $_ = shift; 
    s/ /, /g; 
    return $_;
}

s/(\([^}]*\))/remove_sp($1)/eg;

这会将括号内的空格替换为,例如foo(bar baz) 变为 foo(bar, baz)。但是,它不是很聪明。它还将foo("bar baz") 更改为foo("bar, baz"),这显然不是我想要的。

我想不出一种方法来重写脚本,以便仅当空格不在引号之间时才用逗号空格替换空格。我该怎么做?


这是一个简单的表格,列出了我需要什么以及什么不起作用。

Search                       | Replace                        | Currently handled correctly?
--------------------------------------------------------------------------------------------
foo(bar baz)                 | foo(bar, baz)                  | Yes
foo("bar baz")               | foo("bar baz")                 | No
foo("bar baz" bak)           | foo("bar baz", bak)            | No
foo("bar baz" bak "123 abc") | foo("bar baz", bak, "123 abc") | No

【问题讨论】:

  • @MattJacob 问题出在print("foo bar" baz) 等输入上,应该是print("foo bar", baz)
  • 提示:不要破坏$_!!!至少使用local $_ = shift;,但即使这样也会导致问题,因为$_ 并不罕见地别名为神奇或只读变量。 for (my $s = shift) { ... } 是安全的,但在大多数情况下最好只使用 my $s = shift;

标签: regex perl syntax space removing-whitespace


【解决方案1】:

您可以使用 Text::ParseWords 获取括号之间的数据并对解析结果进行替换。

#!/usr/bin/perl
use strict;
use warnings;
use Text::ParseWords;

for ('foo("bar baz")', 'print("foo bar" baz)', 'foo(bar baz)') {
    my $s = $_;
    $s =~ s/(\([^)]*\))/remove_sp($1)/eg;
    print $s, $/;
}

sub remove_sp {
    join ", ", quotewords('\s+', 1, shift);
}

输出:

foo("bar baz")
print("foo bar", baz)
foo(bar, baz)

【讨论】:

    【解决方案2】:

    我认为这是不可能的。我可以想到几个无法确定是否需要逗号的语法边缘情况:

    字符串粘贴

    foo("abc" "def");   // = foo("abcdef")
    foo("foo", "bar");
    

    将两个字符串常量彼此相邻放置会使它们“粘贴”在一起。如果不知道一个函数需要多少个参数,就无法判断这是否是预期的行为。

    逗号表达式,例如在for 循环中

    The comma is an operator in C;它计算两个表达式并返回 RHS 上一个表达式的值。结合+-&* 运算符的一元/二元对偶性质,这意味着一个简单的表达式:

    a + b    or    a * b
    

    可以插入逗号:

    a, +b    or    a, *b
    

    虽然这是一个人为的例子,但可能会出现更复杂的情况,例如在复杂的for 循环中。

    函数参数

    同样:

    foo(a * b - 1);
    foo(a * b, -1);
    foo(a, *b - 1);
    foo(a, *b, -1);
    (etc)
    

    如果不知道函数预期的参数数量,就不可能判断是否应该插入逗号。有时甚至这还不够!

    【讨论】:

    • 我不是在寻找最佳的 C 语法校正/压缩,只是在必要时添加逗号。我们可以假设逗号应该存在的任何地方都应该存在。
    • 这不是“校正/压缩”的问题。在某些情况下,无法判断逗号是否应该存在。如果可以猜出所有逗号应该在哪里,您就不需要包含它们。 :)
    • 我只是说这个答案超出了问题的范围;我想用逗号替换括号之间的空格,除非空格在引号之间。
    猜你喜欢
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    • 2016-01-30
    • 1970-01-01
    相关资源
    最近更新 更多