正则表达式匹配非空白字符,除了perl的新行

时间:2017-09-20 11:23:38

标签: regex perl

我想匹配第五列,即“,,,”和“,,,,”和“,”除了新行,即“\ n”,然后用一些值替换它们。以下是由空格分隔的文件。我试过以下代码: 注意:虽然该示例在第五列中显示逗号。它可以是除换行符(\ n)之外的任何字符(包括tab \ t)。

let h2 = "ff"
let d4 = Int(h2, radix: 16)!
print(d4) 

数据:

my $delimiter="**";
my $dir_to_check=$DIR; 
opendir my $DIR, $dir_to_check or die "Error in opening dir '$dir_to_check' because: $!";
    my @files = readdir($DIR);
    closedir($DIR);
    foreach my $file (@files)
    {
            if($file =~ /\.fmt/)
            {
                unless ( open( CONTRL_FILE, "< $dir_to_check/$file" ) ) {
                    print "error while opening file $dir_to_check/$file \n"
                }   # UNLESS


               if ($file eq 'test.fmt')
               {
                    unless ( open( CONTRL_FILE_1, "> $dir_to_check/$file.temp" ) ) {
                    print "error while opening file $file \n"
                    }   # UNLESS
                    while(<CONTRL_FILE>)
                    {

                            $_ =~ s/"[^\s]+"/"$delimiter"/ ;
                            print CONTRL_FILE_1 $_;

                    }
                    close(CONTRL_FILE_1);
               }
            }
    }

结果:

1       SQLCHAR             0       5       ",,,"      1     ""
2       SQLCHAR             0       25      ",,,,"      2     ""
3       SQLCHAR             0       1       ","      3     ""
4       SQLCHAR             0       12      ","      4     ""
5       SQLCHAR             0       1       "\n"     5     ""

预期结果:

1       SQLCHAR             0       5       "*****"      1     ""
2       SQLCHAR             0       25      "*****"      2     ""
3       SQLCHAR             0       1       "*****"      3     ""
4       SQLCHAR             0       12      "*****"      4     ""
5       SQLCHAR             0       1       "*****"     5     ""

3 个答案:

答案 0 :(得分:0)

如果您使用的是旧版本的Perl,则可能是一个因素。无论如何,我建议你做一个小修改......

$_ =~ s/"[^\s"]+"/"$delimiter"/;

...这是一个“,一个或多个NOT空白OR”,然后是“

答案 1 :(得分:0)

由于OP在他的评论中说第4列的内容可能是“非空白字符的任意组合”,并且他声称他不希望替换发生在第4列包含“ “从字面上看,我建议他匹配第4列的内容,然后分两步测试引号中的内容是否包含Perl将理解为空格的文字表示。

为此,我们可以使用eval,或者我们可以使用ee modifier的正则表达式,这样更好更安全。

以下是使用后者的示例(更新 - 数据集正确包含OP和其他案例):

#!/usr/bin/perl

use strict;
use warnings;

my $delimiter="**";

while (<DATA>) {
    # we capture the contents of the quotes in
    # 4th column, checking also the expected format
    if (/(^([^\s]+\s+){4})"([^"]+)"(.*)/) {
        my $st = $3;
        # "\n" in the file is actually "\\n" for Perl
        # so, to have Perl understand it as "\n", we need
        # to have Perl effectively escape it, we can
        # do that with a regexp and the ee modifier
        $st =~ s/\\([tnfr])/"qq{\\$1}"/gee;
        # now this will match an "\n", "\r", "\f" or "\t"
        if (!($st =~ /\s/)) {
            print "$1\"$delimiter\"$4\n";
        } else {
            print $_;
        }
    } else {
        print "error: wrong line format: $_\n";
    }
}

__DATA__
1       SQLCHAR             0       5       ",,,"      1     ""
2       SQLCHAR             0       25      ",,,,"      2     ""
3       SQLCHAR             0       1       ","      3     ""
4       SQLCHAR             0       12      ","      4     ""
5       SQLCHAR             0       1       "\n"     5     ""
6       SQLCHAR             0       8       "a b"     6     ""
7       SQLCHAR             0       8       "\t"     7     ""
8       SQLCHAR             0       9       "\"     8     ""
9       SQLCHAR             0       9       "stuff\"     8     ""

会导致:

1       SQLCHAR             0       5       "**"      1     ""
2       SQLCHAR             0       25      "**"      2     ""
3       SQLCHAR             0       1       "**"      3     ""
4       SQLCHAR             0       12      "**"      4     ""
5       SQLCHAR             0       1       "\n"     5     ""
6       SQLCHAR             0       8       "a b"     6     ""
7       SQLCHAR             0       8       "\t"     7     ""
8       SQLCHAR             0       9       "**"     8     ""
9       SQLCHAR             0       9       "**"     8     ""

请注意,没有简单的方法可以确定在给定环境中运行的给定脚本可以理解为“Perl whitespace”,因为它取决于许多因素,并且[\t\n\f\r ]是只是Perl可以理解为空白的简化视图。

引用一点perlrecharclass

  

空白

     

\ s匹配任何被认为是空格的单个字符。

     

如果/ a修饰符生效...

     

在所有Perl版本中,\ s匹配5个字符[\ t \ n \ f \ r];也就是说,水平制表符,换行符,换页符,滑架   回归,空间。从Perl v5.18开始,它也匹配   垂直标签,\ cK。有关此问题的讨论,请参见下面的注释1。   否则......

     

对于255以上的代码点...

     

\ s与下面表格中带有“s”列的255以上的代码点完全匹配。

     

对于256以下的代码点...

     

如果区域设置规则有效......

     

\ s匹配区域设置认为是空格的任何内容。 (...)

答案 2 :(得分:0)

C:\ Users \ Ken&gt;输入test.pl

#!C:\Strawberry\perl\bin\perl -w
$\="\n";
my $d="**";
my $L1="5 SQLCHAR 0 1 \",,,\" 5 \"\"";
my $L2="5 SQLCHAR 0 1 \"\n\" 5 \"\"";
foreach my $L ($L1,$L2)
{
  print "LineIn=$L";
  if ($L=~ s/"[^\s"]+"/"$d"/) {print "#YES L=$L";}
  else {print "#NO  L=$L";}
}

C:\用户\肯&GT; test.pl

LineIn=5 SQLCHAR 0 1 ",,," 5 ""
#YES L=5 SQLCHAR 0 1 "**" 5 ""
LineIn=5 SQLCHAR 0 1 "
" 5 ""
#NO  L=5 SQLCHAR 0 1 "
" 5 ""