子字符串前后的n个字符

时间:2014-05-16 12:46:55

标签: regex perl bash

我正在寻找一种方法(最好是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
...

3 个答案:

答案 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.txtdata.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