我正在寻找一种方法(最好是bash或perl)从较长的字符串中提取子字符串,以便包含子字符串前后的n个字符。我想搜索,说
XXXXXXX
内
....NNNNAAAAXXXXXXXAAAANNNNNNN....
并包含As而不是Ns,因此返回字符串将是
AAAAXXXXXXXAAAA
有什么想法吗?感谢。
一个更好的例子(也许): 我有一个包含唯一字符串列表的文件,
UniqueStr1
UniqueStr2
UniqueStr3
...
包含相同行数的文件,例如
JUNKJUNK_start1_UniqueStr1_end1_JUNKJUNKJUNK
JUNKJUNKJUNKJUNK_start2_UniqueStr2_end2_JUNKJUNKJUNK
start3_UniqueStr3_end3_JUNKJUNK
...
我想要返回一个包含
的文件start1_UniqueStr1_end1
start2_UniqueStr2_end2
start3_UniqueStr3_end3
...
答案 0 :(得分:3)
试试这个:
my $string = 'NNNNAAAAXXXXXXXAAAANNNNNNN';
if ( $string =~ /.{4}XXXXXXX.{4}/ ) {
print $&;
}
如果在提到的子字符串之前的子字符串(在本例中为AAAA)和提到的子字符串之后的子字符串总是相同的,这也是另一种方法。
my $string = 'NNNNAAAAXXXXXXXAAAANNNNNNN';
if ( $string =~ /(.{4})XXXXXXX\1/ ) {
print $&;
}
答案 1 :(得分:2)
目前尚不清楚您要如何定义核心字符串,前缀和后缀。但是这段简短的代码将按照您的要求进行操作
use strict;
use warnings;
while (<DATA>) {
print "$1\n" while /(.{0,7}UniqueStr\d.{0,5})/g;
}
__DATA__
JUNKJUNK_start1_UniqueStr1_end1_JUNKJUNKJUNK
JUNKJUNKJUNKJUNK_start2_UniqueStr2_end2_JUNKJUNKJUNK
start3_UniqueStr1_end3_JUNKJUNK
<强>输出强>
start1_UniqueStr1_end1
start2_UniqueStr2_end2
start3_UniqueStr1_end3
<强>更新强>
如果你想从外部文件中读取数据,比如patterns.txt
和data.txt
,看起来就像使用固定模式UniqueStr\d
作为核心字符串一样,它会构建一个正则表达式来自patterns.txt
的内容使用交替字符|
。这些字符串都是通过quotemeta
映射的,这样如果它们恰好包含任何正则表达式元字符,它们仍然可以工作。
use strict;
use warnings;
use autodie;
open my $fh, '<', 'patterns.txt';
my @patterns = <$fh>;
close $fh;
chomp @patterns;
my $re = join '|', map quotemeta, @patterns;
$re = qr/(.{0,7}(?:$re).{0,5})/;
open $fh, '<', 'data.txt';
while (<$fh>) {
print "$1\n" while /$re/g;
}
输出与上述
相同答案 2 :(得分:1)
此片段提取您指定的目标,并且您可以选择仅选择结果和/或边距。在秒选项中,您还可以确保左边距和右边距相同。
#!/usr/bin/perl
use v5.10;
use strict;
use warnings;
#
# Set the Parameters...
#
my $target = 'XXXXXXX';
my $margin = 4;
#
# Set Position an __DATA__ for later use
#
my $datapos = tell DATA;
#
# Search __DATA__ for a target with arbitary margin...
#
say "=== Option I ===";
while ( <DATA> )
{
while( /(.{$margin})($target)(.{$margin})/g )
{
my $left_margin = $1;
my $result = $2;
my $right_margin = $3;
say $left_margin.$result.$right_margin;
}
}
#
# Restart reading from __DATA__ at the beginnen
#
seek DATA, $datapos, 0;
#
# Search __DATA__ for a target with matching margin...
#
say "=== Option II ===";
while ( <DATA> )
{
while( /(.{$margin})($target)\1/g )
{
my $left_margin = $1;
my $result = $2;
my $right_margin = $1; # Left and right margin are the same
say $left_margin.$result.$right_margin;
}
}
exit;
__DATA__
NNNNAAAAXXXXXXXAAAANNNNNNNNNNNBBBBXXXXXXXBBBBNNNNNNNCCCCXXXXXXXCCC
NNDDDDXXXXXXXDDDDNNNNNNNNEEEEXXXXXXXEEEENNNNNNNFFFFXXXXXXXFFFFNNNN
NNNNGGXXXXXXXGGGGNNNNNNNNNNNHHHHXXXXXXXHNNNNNNNIIIIXXXXXXXIIIINNNN