如何在Perl字符串中去除空格?

13
如果我声明了一个变量$myString,它的值为'3 '(注意尾随空格)。是否有函数可以去除返回值中的空格?类似这样的SomeFun($myString),返回'3'(没有空格)。
#!C:\Perl\bin\perl.exe
use strict;
use warnings;
use Data::Dumper; 

my $fh = \*DATA; 

print Dumper parse_constant_spec( $fh ); 


# Parse a constant spec file. 
# Pass in a handle to process. 
# As long as it acts like a file handle, it will work. 
sub parse_constant_spec { 
    my $fh = shift; 

    my %spec; 

    # Until file is done: 
        # Read in a whole block 
    while( my $block = read_block($fh) ) { 

        # Parse the and return key/value pairs for a hash. 
        my %constant = parse_block( $block ); 

        # Store a ref to the hash in a big hash of all blocks, keyed by constant_name. 
        $spec{ $constant{const_name} } = \%constant; 

    } 

    # Return ref to big hash with all block data 
    return \%spec; 
} 

# Read a constant definition block from a file handle. 
# void return when there is no data left in the file. 
# Otherwise return an array ref containing lines to in the block.  
sub read_block { 
    my $fh = shift; 

    my @lines; 
    my $block_started = 0; 

    while( my $line = <$fh> ) { 

        $block_started++ if $line =~ /^constant/; 

        if( $block_started ) { 

            last if $line =~ /^\s*$/; 

            push @lines, $line; 
        } 
    } 

    return \@lines if @lines; 

    return; 
} 


sub parse_block { 
    my $block = shift; 
    my ($start_line, @attribs) = @$block; 

    my %constant; 

    # Break down first line: 
    # First separate assignment from option list. 
    my ($start_head, $start_tail) = split /=/, $start_line; 

    # work on option list 
    my @options = split /\s+/, $start_head; 

    # Recover constant_name from options: 
    $constant{const_name} = pop @options; 
    $constant{options} = \@options; 

    # Now we parse the value/type specifier 
    @constant{'type', 'value' } = parse_type_value_specifier( $start_tail ); 

    # Parse attribute lines. 
    # since we've already got multiple per line, get them all at once. 
    chomp @attribs; 
    my $attribs = join ' ', @attribs; 

    #  we have one long line of mixed key = "value" or key = <TYPE VALUE>  

    @attribs = $attribs =~ /\s*(\w+\s+=\s+\w+\s+|\w+\s+=\s+".*?"|\w+\s+=\s+<.*?>)\s*/g; 

    for my $attrib ( @attribs ) { 
        warn "$attrib\n"; 
        my ($name, $value) = split /\s*=\s*/, $attrib; 

        if( $value =~ /^"/ ) {  
            $value =~ s/^"|"\s*$//g; 
        } 
        elsif( $value =~ /^</ ) { 
           $value = [ parse_type_value_specifier( $start_tail ) ]; 
        } 
        else { 
            warn "Bad line"; 
        } 

        $constant{ $name } = $value; 
    } 

    return %constant; 
} 

sub parse_type_value_specifier { 
    my $tvs = shift; 

    my ($type, $value) = $tvs =~ /<(\w+)\s+(.*?)>/; 

    return $type, $value; 
} 

__DATA__ 
constant fixup GemEstabCommDelay = <U2 20> 
    vid = 6 
    name = "ESTABLISHCOMMUNICATIONSTIMEOUT" 
    units = "s" 
    min = <U2 0> 
    max = <U2 1800> 
    default = <U2 20> 


constant fixup private GemConstantFileName = <A "C:\\TMP\\CONST.LOG"> 
    vid = 4 
    name = ""  units = "" 


constant fixup private GemAlarmFileName = <A "C:\\TMP\\ALARM.LOG"> 
    vid = 0 
    name = "" 
    units = ""   

输出:

D:\learning\perl>hello1.pl
vid = 6
Bad line at D:\learning\perl\hello1.pl line 102, <DATA> line 8.
name = "ESTABLISHCOMMUNICATIONSTIMEOUT"
units = "s"
min = <U2 0>
max = <U2 1800>
default = <U2 20>
vid = 4
Bad line at D:\learning\perl\hello1.pl line 102, <DATA> line 13.
name = ""
units = ""
vid = 0
Bad line at D:\learning\perl\hello1.pl line 102, <DATA> line 18.
name = ""
units = ""
$VAR1 = {
          'GemAlarmFileName' => {
                                  'vid' => '0      ',
                                  'options' => [
                                                 'constant',
                                                 'fixup',
                                                 'private'
                                               ],
                                  'value' => '"C:\\\\TMP\\\\ALARM.LOG"',
                                  'name' => '',
                                  'type' => 'A',
                                  'const_name' => 'GemAlarmFileName',
                                  'units' => ''
                                },
          'GemEstabCommDelay' => {
                                   'vid' => '6      ',
                                   'options' => [
                                                  'constant',
                                                  'fixup'
                                                ],
                                   'value' => '20',
                                   'min' => [
                                              'U2',
                                              '20'
                                            ],
                                   'name' => 'ESTABLISHCOMMUNICATIONSTIMEOUT',
                                   'max' => [
                                              'U2',
                                              '20'
                                            ],
                                   'default' => [
                                                  'U2',
                                                  '20'
                                                ],
                                   'type' => 'U2',
                                   'units' => 's',
                                   'const_name' => 'GemEstabCommDelay'
                                 },
          'GemConstantFileName' => {
                                     'vid' => '4      ',
                                     'options' => [
                                                    'constant',
                                                    'fixup',
                                                    'private'
                                                  ],
                                     'value' => '"C:\\\\TMP\\\\CONST.LOG"',
                                     'name' => '',
                                     'type' => 'A',
                                     'const_name' => 'GemConstantFileName',
                                     'units' => ''
                                   }
        };

D:\learning\perl>

你可能会注意到'vid' => '0 ',(注意空格)

上面的代码来自答案。我正在学习它。:-)

谢谢。

12个回答

28
$myString =~ s/^\s*(.*?)\s*$/$1/;

这将从两侧修剪空格。

从右侧开始:

$myString =~ s/\s*$//;

嗨Salsa,它运行良好。按照您的指南,$value =~ s/\s*$//; 然后调用 print DEST_XML_FILE "\"$value\""; - Nano HE
3
我对此感到困惑... 我认为最好使用非贪婪捕获: (.*?)。 - Roman
不确定我的方法是否正确,但对我有效。我想从数据库中获取的文件名中删除所有制表符。我使用了 $var=~s/\t//gs; 这段代码可以从字符串中删除所有的 \t。这篇帖子 对我帮助很大。 - Parik Tiwari

16

如果你的空格只有空格字符,那么以下代码将删除所有空格:

$mystring =~ tr/ //ds;

+1。它运行良好。但是我感觉你的脚本语法有点奇怪,根据我的知识很难理解 :-) - Nano HE
1
这是最简单的解决方案。如果您不习惯在perl中操作字符串,我同意语法很奇怪。 tr 用于替换字符串中的字符。如上所述,它表示:用空格 / / 替换为无 //。下面的 ds 是一个修饰符,使命令完整,但在此示例中可能不必要。可以在此处找到一个很好的解释 链接 - Tereus Scott

11
sub trim($)
{
    my $string = shift;
    $string =~ s/^\s+//;
    $string =~ s/\s+$//;
    return $string;
}


print trim($myString)

嗨GxG。我测试了你的代码。print DEST_XML_FILE trim("\"$value\""); 运行良好。否则 print DEST_XML_FILE trim("$value"); 就无法工作。请问你能帮我找出原因吗?我需要使用第一个表达式在变量之间添加双引号。 - Nano HE
1
“\” 代表一个转义序列,所以如果你想要放置双引号,你需要输入 \“ ,否则它会被视为普通的引用文本,而没有引号。” - GxG
嗨 GxG。 当我声明另一个 tempString 时,它能正常工作。 my $tempString = trim($value); 然后调用 print DEST_XML_FILE "\"$tempString\""; 谢谢。 - Nano HE

9

试试这个:

# Delete leading/trailing whitespace.
$string =~ s/^\s+|\s+$//g;

/g 可能会让你失去控制 :) 特别是对于多行字符串内容。更好的方法是使用:$string =~ s/^\s*(.)\s$/$1/; 它适用于带有 /g 选项的多行字符串。 - Znik

5
另一个潜在的替代方案是来自 CPAN 的 Text::Trim,它可以“从字符串中删除前导和/或尾随空格”。它有一个 trim 函数,可能适合您的需求。

2
sub trim
{
    my $str = $_[0];
    $str=~s/^\s+|\s+$//g;
    return $str;
}

print trim(" 4 ");

嗨,ghostdog74。我测试了你的代码。print DEST_XML_FILE trim("\"$value\""); 运行良好。否则 print DEST_XML_FILE trim("$value"); 就无法工作。你能帮我找出原因吗?我需要使用第一个表达式在变量之间添加双引号。 - Nano HE
2
实际上,将前导和尾随空格分别替换掉会更快。那个交替操作会把一切都搞砸。 :) - brian d foy
1
@Nano,替换功能按预期工作。修剪结尾和前导空格。它只是这样做。在将$value传递给trim()函数之前,您应该对其进行任何想要的操作。否则,请展示$value的示例,然后描述修剪后想要看到的内容。 - ghostdog74
@ghostdog74。我更新了整个脚本和输出结果。您能否对$value进行更深入的分析?谢谢。 :-) - Nano HE
@ghostdog74。当我声明另一个tempString时它可以工作。my $tempString = trim($value);然后调用print DEST_XML_FILE "\"$tempString\""; - Nano HE
$string =~ s/^\s*(.)\s$/$1/; 更好用。你可以添加 /g 来修剪所有行。但是 $str=~s/^\s+|\s+$//g; 对于多行的 $str 内容效果不佳。 - Znik

2

以下是一个子程序,可以从字符串中删除前导和尾随空格,并将其中多余的空格替换为一个空格。

-- 子程序

sub unspace { my @stringer = @_ ? @_ : $; $ = join(' ', split(' ')) for @stringer; return wantarray ? @stringer : "@stringer"; }

-- 用法

$MySpacedString = '字符串具有制表符、双空格和其他空白区域。'; $MyCleanString = unspace($MySpacedString);


2

去除字符串中所有的空格:

$string =~ s/ //g;

1

我刚看了一下你的程序,发现有三个地方可以改进或修复。

如果我的代码格式不好,请原谅。 :-(

在你的函数parse_block(...)中,有三个需要注意的项目。

@attribs = $attribs =~ /\s*(\w+\s+=\s+\w+\s+|\w+\s+=\s+".*?"|\w+\s+=\s+<.*?>)\s*/g;

为了消除 vid => '6 ' 后面的空格,只需不在第一个子正则表达式的末尾包含 \s+ 即可。
将其写成:
@attribs = $attribs =~ /\s*(\w+\s+=\s+\w+|\w+\s+=\s+".*?"|\w+\s+=\s+<.*?>)\s*/g;  

$value = [ parse_type_value_specifier( $start_tail ) ];  

你需要的是这个:
$value = [ parse_type_value_specifier( $value ) ]; 

(请注意函数的参数应该是$value而不是$start_tail。你可能没有注意到这一点。)

在@attributes循环中,当'value'有一个普通值(没有""或<...>项目)时,if/else条件中的 'else' 会执行。

更新:将parse_type_value_specifier(...)函数中的参数更改为$value。它被错误地标记为$attrib。


0

从Transact SQL中删除变量$test (eq rtrim(ltrim(@sStr))中的空格:

$test =~s/^\s*(\S*)\s*$/$1/;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接