我想匹配第五列,即“,,,”和“,,,,”和“,”除了新行,即“\ 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 ""
答案 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 ""