如何在大字符串中快速搜索子字符串和周围的字符?



我有一个文件,我需要从中查找每个子字符串实例前后的 10 个字符。

例如,来自:

(1M characters)...ldkS9jfasdfalkasjFalskdfjsDljBASHcslakfjsalZkf4djfsa3Jkjl...(1M characters)

我想要输出:

lskdfjsDljBASHcslakfjsal

当然,在文件中有许多字符串实例,我想以与具有前 10 个字符和后续 10 个字符相同的方式返回所有这些实例。

现在我正在使用grep如下:

grep -o -P '.{0,10}BASH.{0,10}' input.txt > output.txt

虽然这有效,但它似乎非常慢。 有什么方法可以加快这个过程吗? 提前谢谢。

你会尝试以下方法吗:

grep -F 'BASH' input.txt | grep -o -E '.{10}BASH.{10}'

级联多个grep通常看起来像一个反模式,因为 设计不佳的搜索模式。 在这种情况下,它的工作原理如下:第一个grep有效地缩小范围 包含带有-F(固定(选项的目标单词的行; 然后,第二个grep用于提取单词周围的子字符串。

我生成了一个随机字符为 100,000 列的文本文件 和 10,000 行 (1GB(。这是基准测试结果,带有 旧赛扬CPU:

time grep -o -P '.{0,10}BASH.{0,10}' input.txt
=> 2m48s
time grep -F 'BASH' input.txt | grep -o -E '.{10}BASH.{10}'
=> 0m20s

顺便说一句,令人惊讶的是,我在随机生成的字符串中发现了九个BASH字符串 ASCII 文件。

[编辑]

如果您需要保持重叠的匹配,请尝试:

grep -F 'BASH' file | perl -ne 'while (/(?=(.{10}BASH.{10}))/g) {print $1, "n"}'

与上面的答案相比,它不需要额外的执行时间。

我有一个文件,我需要从中找到每个子字符串实例前后的 10 个字符。

从字面上解释,这意味着对grep -o的天真使用通常不能满足要求,因为此选项仅报告非重叠序列。

为了说明这一点,为简单起见,假设感兴趣的子字符串是"X",并且两侧的窗口长度必须为 3。

然后给定字符串"aaaXaaXaaa",输出(根据需求语句(必须是两行:

aaaXaaX
XaaXaaa

下面是一个脚本,用于演示使用 jq 的解决方案:

#!/bin/bash
for x in X aXa aaaXaaa aaaXaaXaaa aaaXXaaa
do
echo $x ::
jq -Rrs --arg ss X --argjson n 3 '
. as $in
| indices($ss)[] as $i
| select($i-$n >=0 and $i+$n <= length)
| $in[$i-$n:$i+$n+1]' <<< "$x"
echo
done

请注意,此处的 -s 选项实际上会导致控制字符(如换行符(被视为单个字符。

输出

X ::
aXa ::
aaaXaaa ::
aaaXaaa
aaaXaaXaaa ::
aaaXaaX
XaaXaaa
aaaXXaaa ::
aaaXXaa
aaXXaaa

最新更新