2012-04-20 86 views
3

我绑拿出一些正则表达式将从字符串,只要它不是双引号(“)内删除所有空间字符在Perl中,如何删除不在双引号内的所有空格“”?

例字符串:

一些字符串”文中引用”

结果:

somestringwith “文本引号”

到目前为止,我已经拿出这样的东西:

$str =~ /"[^"]+"|/g; 

但它似乎并没有给出预期的结果。

我在perl中很老实,而且没有太多正则表达式的经验。所以,如果有人愿意回答,也愿意提供一些有关为什么以及如何将是伟大的洞察力!

谢谢!

编辑

字符串将不包含转义“的

它实际上应该始终格式如下:

Some.String = “一些价值”

结果将是

Some.String =“某个值”

+0

你可以在引号里面加引号吗?例如。 '“引号\”“'中的文本。 – TLP 2012-04-20 14:46:44

+0

不,字符串实际上总是以这种形式出现。 Some.String.Info =“引号中的一些文本”。但是,可能有一些人逃脱了。例如:“有些字符串不会” – francis 2012-04-20 14:48:37

+0

如果字符串是:**某些字符串带有“引号”,然后是“一些”更多引号“**? – ArjunShankar 2012-04-20 14:55:20

回答

5

这是一种使用split分隔引用字符串的技巧。它依赖于你的数据是一致的,不会与宽松的报价一起工作。

use strict; 
use warnings; 

my @line = split /("[^"]*")/; 
for (@line) { 
    unless (/^"/) { 
     s/[ \t]+//g; 
    } 
} 
print @line; # line is altered 

基本上,你分开了字符串以隔离引用的字符串。完成后,对所有其他字符串执行替换。由于数组元素在循环中是别名,所以在实际数组上进行替换。

你可以像这样运行此脚本:

perl -n script.pl inputfile 

要查看输出。或

perl -n -i.bak script.pl inputfile 

要做到对inputfile就地编辑,而在inputfile.bak备份保存。

就这样说,我不确定你的编辑是什么意思。你想通过字符通过串字符改变

Some.String = "Some Value" 

Some.String="Some Value" 
+0

完美,谢谢! – francis 2012-04-20 15:13:20

+0

@ f-a欢迎您。 – TLP 2012-04-20 15:16:31

+0

好奇地使用“分隔符保留模式”:) – 2012-04-20 20:10:51

0

我就简单循环。这样你也可以处理转义字符串(只需添加一个isEscaped变量)。

my $text='lala "some thing with quotes " lala ... '; 
my $quoteOpen = 0; 
my $out; 

foreach $char(split//,$text) { 
    if ($char eq "\"" && $quoteOpen==0) { 
    $quoteOpen = 1; 
    $out .= $char; 
    } elsif ($char eq "\"" && $quoteOpen==1) { 
    $quoteOpen = 0; 
    $out .= $char; 
    } elsif ($char =~ /\s/ && $quoteOpen==1) { 
    $out .= $char; 
    } elsif ($char !~ /\s/) { 
    $out .= $char; 
    } 
} 

print "$out\n"; 
1

我建议使用split去除引述子,然后从中间文本删除空白后join他们进行重新组合。

请注意,如果用于split的正则表达式包含捕获,则捕获的值也将包含在返回的列表中。

下面是一些示例代码。

use strict; 
use warnings; 

my $source = <<END; 
Some.String = "Some Value"; 
Other.String = "Other Value"; 
Last.String = "Last Value"; 
END 

print join '', map {s/\s+// unless /"/; $_; } split /("[^"]*")/, $source; 

输出

Some.String= "Some Value";Other.String = "Other Value";Last.String = "Last Value"; 
+0

'join'在void(print)上下文中是多余的,除非'$,'被设置为某个定义的值。一个更具启发性的例子可能是将'join'语句分配给标量。 – TLP 2012-04-20 15:15:48

+0

您的替换应该包含g(全局)修饰符。 – 2012-04-25 15:00:04

3

Text::ParseWords是量身订做此:

#!/usr/bin/env perl 

use strict; 
use warnings; 
use Text::ParseWords; 

my @strings = (
    q{This.string = "Hello World"}, 
    q{That " string " and "another shoutout to my bytes"}, 
); 

for my $s (@strings) { 
    my @words = quotewords '\s+', 1, $s; 
    print join('', @words), "\n"; 
} 

输出:

This.string="Hello World" 
That" string "and"another shoutout to my bytes"

使用Text::ParseWords意味着如果你曾经处理引号中带有引号的字符串,你会准备好;-)

此外,这听起来像你有某种配置文件,你试图解析它。如果是这种情况,那么可能会有更好的解决方案。

+0

谢谢,我要看看这个。 – francis 2012-04-20 15:15:13

0

上双引号分割,仅由偶数场去掉空格(即那些引号):

s/([^ ]*|\"[^\"]*\") */$1/g 

注意这不会处理:

sub remove_spaces { 
    my $string = shift; 
    my @fields = split /"/, $string . ' '; # trailing space needed to keep final " in output 
    my $flag = 1; 
    return join '"', map { s/ +//g if $flag; $flag = ! $flag; $_} @fields; 
} 
0

它可以与正则表达式来完成引号内的任何类型的逃脱。