在perl中使用替换运算符跳过字符串中的特定位置
昨天,我被一个perl脚本卡住了。让我简化一下,假设有一个字符串(比如abcdeabcdeabcdeabcdeabcdeabcd),首先我必须在“E”出现的每个位置断开它,其次,在用户想要的位置断开它。但是,条件是,程序不应该在E后面跟P的位置进行剪切。例如,在这个序列中有6个E,所以应该得到7个片段,但是当2个E后面跟P时,输出中只会得到5个片段 关于第二个案子我需要帮助。假设用户不想在序列中E的第5和第10个位置剪切这个序列,那么对应的脚本应该是什么,让程序只跳过这两个位置?第一个案例的脚本是:在perl中使用替换运算符跳过字符串中的特定位置,perl,skip,string-substitution,Perl,Skip,String Substitution,昨天,我被一个perl脚本卡住了。让我简化一下,假设有一个字符串(比如abcdeabcdeabcdeabcdeabcdeabcd),首先我必须在“E”出现的每个位置断开它,其次,在用户想要的位置断开它。但是,条件是,程序不应该在E后面跟P的位置进行剪切。例如,在这个序列中有6个E,所以应该得到7个片段,但是当2个E后面跟P时,输出中只会得到5个片段 关于第二个案子我需要帮助。假设用户不想在序列中E的第5和第10个位置剪切这个序列,那么对应的脚本应该是什么,让程序只跳过这两个位置?第一个案例的脚本
my $otext = 'ABCDEABCDEABCDEPABCDEABCDEPABCDEABCD';
$otext=~ s/([E])/$1=/g; #Main cut rule.
$otext=~ s/=P/P/g;
@output = split( /\=/, $otext);
print "@output";
请帮忙 要在“E”上拆分,除非后面跟“p”,您应该使用否定的前瞻断言
从“环视断言”部分:
- (?!模式)
零宽度负前瞻断言。
例如
匹配任何不后跟“bar”的“foo”匹配项。/foo(?!bar)/
现在,为了避免在发生第2次和第4次时切割,您可以做两件事:
my %no_cuts = map { ($_=>1) } (2,4); # Do not cut in positions 2,4
my @output_final;
for(my $i=0; $i < @output; $i++) {
if ($no_cuts{$i}) {
$output_final[-1] .= $output[$i];
} else {
push @output_final, $output[$i];
}
}
print Data::Dumper->Dump([\@output_final];
$VAR1 = [
'ABCD',
'ABCDABCDEPABCD',
'ABCDEPABCDABCD'
];
my%no_cuts=map{($u=>1)}(2,4)#不要在位置2,4处切割
我的@output_final;
对于(我的$i=0;$i<@output;$i++){
如果($no_{$i}){
$output_final[-1]。=$output[$i];
}否则{
推送@output_final,$output[$i];
}
}
打印数据::转储程序->转储([\@output\u final];
$VAR1=[
"ABCD",,
“ABCDABCDEPABCD”,
“ABCDEPABCDABCD”
];
或者更简单一点:
my %no_cuts = map { ($_=>1) } (2,4); # Do not cut in positions 2,4
for(my $i=0; $i < @output; $i++) {
$output[$i-1] .= $output[$i];
$output[$i]=undef; # Make the slot empty
}
my @output_final = grep {$_} @output; # Skip empty slots
print Data::Dumper->Dump([\@output_final];
$VAR1 = [
'ABCD',
'ABCDABCDEPABCD',
'ABCDEPABCDABCD'
];
my%no_cuts=map{($=>1)}(2,4);#不要在位置2,4进行剪切
对于(我的$i=0;$i<@output;$i++){
$output[$i-1]。=$output[$i];
$output[$i]=undef;#使插槽为空
}
my@output\u final=grep{$\u}@output;#跳过空槽
打印数据::转储程序->转储([\@output\u final];
$VAR1=[
"ABCD",,
“ABCDABCDEPABCD”,
“ABCDEPABCDABCD”
];
- (?!模式)
零宽度负前瞻断言。
例如
匹配任何不后跟“bar”的“foo”匹配项。/foo(?!bar)/
现在,为了避免在发生第2次和第4次时切割,您可以做两件事:
my %no_cuts = map { ($_=>1) } (2,4); # Do not cut in positions 2,4
my @output_final;
for(my $i=0; $i < @output; $i++) {
if ($no_cuts{$i}) {
$output_final[-1] .= $output[$i];
} else {
push @output_final, $output[$i];
}
}
print Data::Dumper->Dump([\@output_final];
$VAR1 = [
'ABCD',
'ABCDABCDEPABCD',
'ABCDEPABCDABCD'
];
my%no_cuts=map{($=>1)}(2,4);#不要在位置2,4进行剪切
我的@output_final;
对于(我的$i=0;$i<@output;$i++){
如果($no_{$i}){
$output_final[-1]。=$output[$i];
}否则{
推送@output_final,$output[$i];
}
}
打印数据::转储程序->转储([\@output\u final];
$VAR1=[
"ABCD",,
“ABCDABCDEPABCD”,
“ABCDEPABCDABCD”
];
或者更简单一点:
my %no_cuts = map { ($_=>1) } (2,4); # Do not cut in positions 2,4
for(my $i=0; $i < @output; $i++) {
$output[$i-1] .= $output[$i];
$output[$i]=undef; # Make the slot empty
}
my @output_final = grep {$_} @output; # Skip empty slots
print Data::Dumper->Dump([\@output_final];
$VAR1 = [
'ABCD',
'ABCDABCDEPABCD',
'ABCDEPABCDABCD'
];
my%no_cuts=map{($=>1)}(2,4);#不要在位置2,4进行剪切
对于(我的$i=0;$i<@output;$i++){
$output[$i-1]。=$output[$i];
$output[$i]=undef;#使插槽为空
}
my@output\u final=grep{$\u}@output;#跳过空槽
打印数据::转储程序->转储([\@output\u final];
$VAR1=[
"ABCD",,
“ABCDABCDEPABCD”,
“ABCDEPABCDABCD”
];
这是一个利用两个事实的肮脏伎俩:
- 普通文本字符串从不包含空字节(如果您不知道空字节是什么,作为程序员,您应该:,和nb。它与数字0或字符0不同)
- 如果将perl字符串放在那里,它们可能包含空字节,但请小心,因为这可能会破坏一些perl内部函数
my $s = "ABCDEABCDEABCDEPABCDEABCDEPABCDEABCD";
my @nobreak = (4,9);
foreach (@nobreak) {
substr($s, $_, 1) = "\0";
}
“\0”
是一个转义序列,表示一个空字节,如“\t”
是一个制表符。同样,它不是字符0。我使用了4和9,因为在这些位置有E。如果现在打印字符串,它看起来像:
ABCDABCDABCDEPABCDEABCDEPABCDEABCD
因为不显示空字节,但它们在那里,我们稍后会将它们交换回。首先,拆分:
my @a = split(/E(?!P)/, $s);
然后将零字节交换回:
$_ =~ s/\0/E/g foreach (@a);
如果现在打印@a
,您将获得:
ABCDEABCDEABCDEPABCD
ABCDEPABCD
ABCD
这正是您想要的。请注意,split会删除分隔符(在本例中为E);如果您打算保留这些分隔符,则可以在以后将其重新加上。如果分隔符来自更动态的正则表达式,则会稍微复杂一些,请参阅此处:
“示例9.保留分隔符”
如果有可能
@nobreak
位置不是E,那么在替换它们时,您还必须跟踪它们,以确保再次替换为正确的字符。下面是一个利用两个事实的肮脏伎俩:
- 普通文本字符串从不包含空字节(如果您不知道空字节是什么,作为程序员,您应该:,和nb。它与数字0或字符0不同)
- perl字符串c