perl - 从awk中的文件中提取前后字符到匹配的字符串
问题描述
我有一个大seq.txt
的字母字符串文件,未包装,超过 200,000 个字符。没有空格、数字等,只有 az。
我有第二个文件search.txt
,其中包含 50 个唯一字母的行,它们将在seq.txt
. 有 4000 种模式可供匹配。
我希望能够找到每个模式(文件中的行search.txt
),然后获取模式匹配之前的 100 个字符和之后的 100 个字符。
我有一个使用 grep 并且可以运行的脚本,但是它运行得很慢,只处理前 100 个字符,并且用 echo 写出。我在 awk 或 perl 方面的知识不足,无法在线解释可能适用的脚本,所以我希望这里有人!
cat search.txt | while read p; do echo "grep -zoP '.{0,100}$p' seq.txt | sed G"; done > do.grep
具有所需输出的更简单示例:
>head seq.txt
abcdefghijklmnopqrstuvwxyz
>head search.txt
fgh
pqr
uvw
>head desiredoutput.txt
cdefghijk
mnopqrstu
rstuvwxyz
最好的结果是一个制表符分隔的文件100 characters before \t matched pattern \t 100 characters after
。先感谢您!
解决方案
单程
use warnings;
use strict;
use feature 'say';
my $string;
# Read submitted files line by line (or STDIN if @ARGV is empty)
while (<>) {
chomp;
$string = $_;
last; # just in case, as we need ONE line
}
# $string = q(abcdefghijklmnopqrstuvwxyz); # test
my $padding = 3; # for the given test sample
my @patterns = do {
my $search_file = 'search.txt';
open my $fh, '<', $search_file or die "Can't open $search_file: $!";
<$fh>;
};
chomp @patterns;
# my @patterns = qw(bcd fgh pqr uvw); # test
foreach my $patt (@patterns) {
if ( $string =~ m/(.{0,$padding}) ($patt) (.{0,$padding})/x ) {
say "$1\t$2\t$3";
# or
# printf "%-3s\t%3s%3s\n", $1, $2, $3;
}
}
作为 运行program.pl seq.txt
,或将其内容通过管道seq.txt
传输给它。†</sup>
模式.{0,$padding}
匹配任何字符.
(_ $padding
_ 3
_ $patt
_问题)。之后的填充也是如此。$padding
bcd
$patt
在您的问题中,然后替换$padding
为100
. 使用100
每个模式之前和之后的宽“填充”,当在比 100 更接近开始的位置找到模式时\t
,如果该位置小于 100 大于制表符值(通常为 8 )。
这就是带有格式化的 print ( printf
) 的行的用途,以确保每个字段的宽度,而不管正在打印的字符串的长度如何。(它被注释掉,因为我们被告知没有模式进入第一个或最后 100 个字符。)
如果匹配的模式确实不可能突破第一个或最后 100 个位置,那么正则表达式可以简化为
/(.{$padding}) ($patt) (.{$padding})/x
请注意,如果 a$patt
在第一个/最后一个$padding
字符内,那么这将不匹配。
该程序为每个 启动正则表达式引擎,@patterns
原则上可能会引发性能问题(不是一次运行少量的 4000 个模式,但这样的要求往往会发生变化并且通常会增长)。但这是迄今为止最简单的方法
我们不知道模式如何在字符串中分布,并且
一场比赛可能在另一场比赛的 100 字符缓冲区内(我们没有被告知其他情况)
如果此方法存在性能问题,请更新。
†</sup> 程序的输入(和输出)可以通过使用命名命令行参数以更好的方式组织,Getopt::Long
例如
program.pl --sequence seq.txt --search search.txt --padding 100
其中每个参数在这里可能是可选的,在文件中设置默认值,并且参数名称可能会缩短和/或给定其他名称等。如果感兴趣,请告诉我
推荐阅读
- rust - 如何在 Rust 中的定位索引处获取位值?
- python - 我必须修改错误的代码。但是我卡在下面的部分,我在 python 中遇到了这个错误
- reactjs - 如何在不将类应用于每个元素的情况下更改单个反应组件中所有 Material UI Typography 组件的样式?
- arrays - 使数组的对和相等的最小操作数
- excel - 为“#VALUE!”的 Cell.Value 抛出类型不匹配做准备 在 Visual Basic 宏中
- dom - Javascript DOM 寻址到子窗口 DOM 元素
- android - 为什么片段的背景设置为某种颜色时工具栏会消失?
- c++ - 清除ncurses屏幕c ++的特定部分
- python - E: 找不到包 python-pygraphviz E: 包 'ipython' 没有安装候选
- python - TypeError:'int'和'function'的实例之间不支持'<='