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