我想计算里面存在的空格数量:() OR ""。
可以使用 perl 正则表达式来完成吗?
示例:
设字符串为:
abcd(efg h i)jkl -> count = 2
abc def(dfdsff fd)dfdsf -> count = 1
( )(?=[^"]*"(?:[^"]*"[^"]*")*[^"]*$)|( )(?=[^(]*\))
你可以试试这个。计算组数。参见演示。
https://regex101.com/r/zM7yV5/6
在这里我们找到
space
,它位于""
或()
内部。一旦我们发现,我们捕获并计算我们找到的组的数量,这就是答案。
( )(?=[^"]*"(?:[^"]*"[^"]*")*[^"]*$)
==>这里先行确保它在它前面找到一个"
,然后在它前面找到一组""
。简而言之,它前面有奇数个"
。这使我们能够选择space
它位于 ""
之间,因为它前面有奇数个 "
。
( )(?=[^(]*\))
==> hre Lookahead 意味着它应该在没有 )
的情况下找到前面的 (
。因此,这使我们能够捕获 ()
之间的空间。尽管这对于嵌套的 ()
不起作用。
您可以使用正则表达式来查找并捕获括号内的字符串,并使用
tr///
来计算捕获的字符串中空格字符的数量。
该程序演示了原理。它从
DATA
文件句柄中读取字符串(我使用了您问题中的示例数据,但复制了它以提供包含双引号的示例),并假设每个中只有一对括号或引号字符串。
我使用了 branch Reset 构造 (?| ... )
,以便在
$1
中捕获括号内的内容,无论匹配的是括号还是双引号。如果假设不成立,修改代码是一件简单的事情,但你已经在评论中被问到了,但没有提供答案。
use strict;
use warnings;
use List::Util 'max';
my $re = qr/ (?|
\( ( [^()]+ ) \)
|
" ( [^()]+ ) "
) /x;
my @data = <DATA>;
chomp @data;
my $width = max map length, @data;
for (@data) {
chomp;
if ( $_ =~ $re ) {
my $count = $1 =~ tr/\x20\t//;
printf "%-*s -> count = %d\n", $width, $_, $count;
}
}
__DATA__
abcd(efg h i)jkl
abc def(dfdsff fd)dfdsf
abcd"efg h i"jkl
abc def"dfdsff fd"dfdsf
abcd(efg h i)jkl -> count = 2
abc def(dfdsff fd)dfdsf -> count = 1
abcd"efg h i"jkl -> count = 2
abc def"dfdsff fd"dfdsf -> count = 1
我认为这种方式更容易理解一点,并且不需要 CPAN 的任何东西。 基本上捕获全局匹配中每行中的所有空格。 将其放入字符串中。 然后使用字符串的长度作为每行中的空白总数。 这是代码
#!/usr/bin/perl -w
my $whitespaceTotal = ""; #total whitespace in file
while(<>){
chomp;
my $whitespaceMatched = ""; #total whitespace in double quote or parethesis
my $pattern = "";
if( /\"(.+)\"/ || /\((.+)\)/){ #match anything inside double quotes or parenthesis
$pattern = $1; #first backreference starts at left most parenthesis
}
while( $pattern =~ /( +)/g ){
$whitespaceMatched = $whitespaceMatched . $1; #append all whitespace to string
} #Total whitespace is length($whitespaceMatched)
printf("%-37s -> %s\n", "\'".$_."\'", length($whitespaceMatched)); #left align string with quotes. For longer strings increase -37 to match the length of the string
$whitespaceTotal = $whitespaceTotal . $whitespaceMatched; #tally all whitespace total
}
print "\nTotal Whitespace " . length($whitespaceTotal) . "\n"; #print total whitespace found
输出看起来像这样
perl countWhitespace.pl countWhitespace.txt
'abcd(efg h i)jkl' -> 2
'abc def(dfdsff fd)dfdsf' -> 1
'abcd"efg h i"jkl ' -> 2
'abc def"dfdsff fd"dfdsf' -> 1
'no parenthesis or double quotes' -> 0
'parenthesis (withnospacesinside)' -> 0
'parenthesis (with spaces inside)' -> 2
'doublequotes "withnospacesinside"' -> 0
'doublequotes "with spaces inside"' -> 2
'empty parenthesis ()' -> 0
'empty double quotes ""' -> 0
'' -> 0
'"above line was empty" ' -> 3
'(previous line had trailing spaces)' -> 4
'double quote with only space " "' -> 4
'parenthesis with only space ( )' -> 4
Total Whitespace 25
祝你好运!