【问题标题】:How do I remove white space in a Perl string?如何删除 Perl 字符串中的空格?
【发布时间】:2010-01-08 05:14:17
【问题描述】:

如果我用值'3 ' 声明了一个变量$myString(注意空格)。 是否有任何功能可以删除返回值的空白。 有点像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' =&gt; '0 ',(注意空格)

以上代码来自the answer。我正在研究它。 :-)

谢谢。

【问题讨论】:

    标签: perl


    【解决方案1】:
    $myString =~ s/^\s*(.*?)\s*$/$1/;
    

    这将修剪两边的空白。

    从右边:

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

    【讨论】:

    • 嗨莎莎。它运作良好。跟着你的向导,$value =~ s/\s*$//; 然后打电话给print DEST_XML_FILE "\"$value\"";
    • 我遇到了麻烦。我认为使用非贪婪捕获会更好:(.*?)
    • 不确定我的方法是否正确,但对我有用。我想删除从 db.xml 获取的文件名中的所有选项卡。我使用$var=~s/\t//gs; 代码删除了字符串中的所有\t。 This post 帮了我很多。
    【解决方案2】:

    如果您的空白只是空格,那么以下代码将删除所有空格:

    $mystring =~ tr/ //ds;
    

    【讨论】:

    • +1 。它运作良好。但是我觉得你的脚本语法有点奇怪,根据我的知识很难理解:-)
    • 这是最简单的解决方案。如果您不习惯在 perl 中操作字符串,我同意语法很奇怪。 tr 用于替换字符串中的字符。如上所述,它说:将空格/ / 替换为空//。以下 ds 是使命令完整的修饰符,但在此示例中可能不是必需的。一个很好的解释可以在这里找到link
    【解决方案3】:
    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"); 无法工作。你能帮我找出原因吗?我需要使用第一个表达式在变量之间添加双引号。
    • \" 代表一个转义序列,所以如果你想加引号,你需要放 \" 否则它将被视为一个简单的带引号的文本,并且会出现没有引号
    • 嗨,GxG。当我声明另一个 tempString 时它起作用了。 my $tempString = trim($value); 然后拨打print DEST_XML_FILE "\"$tempString\""; 谢谢。
    【解决方案4】:

    试试这个:

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

    【讨论】:

    • /g 可能会失去你 :) 专门用于多行字符串内容。为了更好地使用一步: $string =~ s/^\s*(.*)\s*$/$1/;它可用于带有 /g 选项的多行。
    【解决方案5】:

    另一个潜在的替代解决方案是来自 CPAN 的 Text::Trim,它将“从字符串中删除前导和/或尾随空格”。它有一个trim 函数,可以满足你的需要。

    【讨论】:

      【解决方案6】:
      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,交替按预期工作。修剪结尾和前导空格。就是这样。在将 $value 传递给 trim() 函数之前,你应该做任何你想做的事情。否则,请举例说明 $value 是什么,然后描述修剪后您希望看到的内容。
      • @ghostdog74。我更新了整个脚本和它的输出。请您对 $value 做更多的剖析。谢谢你。 :-)
      • @ghostdog74。当我声明另一个 tempString 时它起作用了。 my $tempString = trim($value); 然后拨打print DEST_XML_FILE "\"$tempString\"";
      【解决方案7】:

      这是一个子例程,可让您从字符串中删除前导和尾随空格,同时从字符串中删除多余的空格并将其替换为单个空格。

      <pre></pre>

      --例程

      sub unspace { 我的@stringer = @_ ? @_ : $; $ = join( ' ', split(' ')) for @stringer; 返回想要数组? @stringer : "@stringer"; }

      --用法

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

      【讨论】:

        【解决方案8】:

        仅查看您的程序,我发现了 3 个可以改进或修复的地方。

        如果我的代码格式不正确,我深表歉意。 :-(

        在您的函数 parse_block(...) 中,有 3 项需要注意。

        @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' 具有普通值('value' 中没有“”或<...> 项),if/else 条件中的'else' 将执行。

        更新:更改参数

        parse_type_value_specifier(...)
        到 $value。它被(错误地)表示为 $attrib。

        【讨论】:

          【解决方案9】:

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

          $string =~ s/ //g;
          

          【讨论】:

            【解决方案10】:

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

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

            【讨论】:

              【解决方案11】:

              如果您愿意使用 CPAN 模块,那么String::Util,或者更经济的Text::Trim 将是可能的选择。

              修剪线是每个人都喜欢建造的自行车棚之一!请参阅 @szabgab 的短片 perlmaven tutorial,了解 TIMTOWDI 乐趣的小样本。

              【讨论】:

                【解决方案12】:

                我建议你使用Text::Trim模块,它提供了ltrimrtrimtrim,所有这些都会修剪传递的参数,如果你不给任何参数,则使用$_。它不是核心模块,因此可能需要安装

                【讨论】:

                  猜你喜欢
                  • 2011-09-30
                  • 2021-09-04
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-02-02
                  相关资源
                  最近更新 更多