在C源中插入缺少的逗号

时间:2018-02-28 00:41:02

标签: regex perl syntax space removing-whitespace

我有一个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

2 个答案:

答案 0 :(得分:3)

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

字符串粘贴

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)

如果不知道函数所需的参数数量,就无法确定是否应该插入逗号。有时即使这还不够!

答案 1 :(得分:2)

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

#!/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)