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

Regex 如何快速搜索大字符串中的子字符串和周围字符?,regex,linux,bash,grep,substring,jq,Regex,Linux,Bash,Grep,Substring,Jq,我有一个文件,我需要在每个子字符串实例前后找到10个字符 例如,来自: 1M个字符…LDKS9JFASDFALKASJFALSKDFJSDLJBASHCLAKFJSALZKF4DJFSA3JKJL…1M个字符 我希望输出: lskdfjsDljBASHcslakfjsal 当然,在文件中有许多字符串实例,我希望以相同的方式返回所有实例,包括前面和后面的10个字符 现在,我正在使用grep,如下所示: grep-o-P'{0,10}BASH.{0,10}'input.txt>output.txt

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

例如,来自:

1M个字符…LDKS9JFASDFALKASJFALSKDFJSDLJBASHCLAKFJSALZKF4DJFSA3JKJL…1M个字符 我希望输出:

lskdfjsDljBASHcslakfjsal 当然,在文件中有许多字符串实例,我希望以相同的方式返回所有实例,包括前面和后面的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 fixed选项的目标词的行; 然后第二个grep将提取单词周围的子字符串

我已经生成了一个包含100000列随机字符的文本文件 和10000行1G字节。下面是带有 旧赛扬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
顺便说一句,我在随机生成的 ascii文件

[编辑]

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

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

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

您是否可以尝试以下方法:

grep -F 'BASH' input.txt | grep -o -E '.{10}BASH.{10}'
由于以下原因,级联多个grep通常看起来像一个反模式: 设计糟糕的搜索模式。 在这种情况下,它的工作原理如下:第一个grep有效地缩小了范围 包含带有-F fixed选项的目标词的行; 然后第二个grep将提取单词周围的子字符串

我已经生成了一个包含100000列随机字符的文本文件 和10000行1G字节。下面是带有 旧赛扬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
顺便说一句,我在随机生成的 ascii文件

[编辑]

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

grep -F 'BASH' file | perl -ne 'while (/(?=(.{10}BASH.{10}))/g) {print $1, "\n"}'
与上面的答案相比,它不需要额外的执行时间

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

从字面上解释,这意味着grep-o的简单使用通常不能满足要求,因为这个选项只报告非重叠序列

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

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

aaaXaaX
XaaXaaa
下面是一个脚本,它演示了一个使用以下内容的解决方案:

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

从字面上解释,这意味着grep-o的简单使用通常不能满足要求,因为这个选项只报告非重叠序列

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

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

aaaXaaX
XaaXaaa
下面是一个脚本,它演示了一个使用以下内容的解决方案:


是否有理由在字符串前后搜索0到10个字符,而不是仅仅搜索10个字符?从您描述问题的方式来看,似乎两边都至少有10个,如果在输入的开头或结尾附近有一个字符串实例,则可以通过额外的、简单的快速步骤捕获。{10} BASH.{10}应该快得多。谢谢你,CAustin,我会试试这个。老实说,我认为{0,10}表示从位置0到10的每个字符。我只希望两边各有10个字符。@FightingTime不,这意味着BASH前面至少有0个字符和atmost 10个字符。因此,对于这个BASHsad字符串,其中BASH在开始时存在,您的正则表达式应该找到一个匹配项,而Austin的不匹配项,因为BASH前面有0个字符,所以可以看到如下问题:and.try awk-v RS='.{10}BASH.{10}'{print RT}'。。。另外,如果输入都是ASCII码,那么使用LC_all=C awk-v RS='.{10}BASH.{10}'{print RT}'将得到更好的结果。。。和格雷普一样。。。LC_ALL=C grep-oE'{10}BASH.{10}'是否有理由在字符串前后搜索0到10个字符,而不仅仅是10个字符?从您描述问题的方式来看,似乎两边都至少有10个,如果在输入的开头或结尾附近有一个字符串实例,则可以通过额外的、简单的快速步骤捕获。{10} BASH.{10}应该快得多。谢谢你,CAustin,我会试试这个。老实说,我认为{0,10}表示从位置0到10的每个字符。我只想
t两边各有10个字符。@FightingTime不,它表示BASH前面至少有0个字符和atmost 10个字符。因此,对于这个BASHsad字符串,其中BASH在开始时存在,您的正则表达式应该找到一个匹配项,而Austin的不匹配项,因为BASH前面有0个字符,所以可以看到如下问题:and.try awk-v RS='.{10}BASH.{10}'{print RT}'。。。另外,如果输入都是ASCII码,那么使用LC_all=C awk-v RS='.{10}BASH.{10}'{print RT}'将得到更好的结果。。。和格雷普一样。。。LC_ALL=C grep-oE.{10}BASH.{10}'注意,-o选项只报告不重叠的匹配,因此使用此技术不会单独报告靠得太近的BASH事件。@peak感谢您的评论。你是对的,但是OP的代码也指定了-o选项,我认为结果与OP的结果在这个意义上没有区别。如果我们需要分离重叠的子串,那么只需要少量的额外时间就可以实现。无论如何,这取决于OP的要求。明白了,但我需要在每个子字符串实例前后找到10个字符的主要问题陈述与迄今为止提出的各种解决方案之间的差异可能并不明显。当然,这可能也不重要:-@Sundeep谢谢你的评论。至于时间比较,我把{0,10}改为{10}并没有赋予它深刻的意义。我应该一个一个地改变条件。实际上,{0,10}和{10}之间的时间没有差别。考虑到目标词位于行首或行尾的情况,最好使用{0,10}。我已经安装了rg,并使用您建议的代码测量了性能。在同样的条件下花了40秒。比原来的grep快得惊人,但我的建议似乎仍然有效。BR@Sundeep我也测试过:`rg-F'BASH'文件| rg-oP'{10}BASH?=.{10}'-r'$0$1',结果只需要0.6秒!请注意,-o选项只报告非重叠的匹配,因此使用此技术不会单独报告靠得太近的BASH事件。@谢谢您的评论。你是对的,但是OP的代码也指定了-o选项,我认为结果与OP的结果在这个意义上没有区别。如果我们需要分离重叠的子串,那么只需要少量的额外时间就可以实现。无论如何,这取决于OP的要求。明白了,但我需要在每个子字符串实例前后找到10个字符的主要问题陈述与迄今为止提出的各种解决方案之间的差异可能并不明显。当然,这可能也不重要:-@Sundeep谢谢你的评论。至于时间比较,我把{0,10}改为{10}并没有赋予它深刻的意义。我应该一个一个地改变条件。实际上,{0,10}和{10}之间的时间没有差别。考虑到目标词位于行首或行尾的情况,最好使用{0,10}。我已经安装了rg,并使用您建议的代码测量了性能。在同样的条件下花了40秒。比原来的grep快得惊人,但我的建议似乎仍然有效。BR@Sundeep我也测试过:`rg-F'BASH'文件| rg-oP'{10}BASH?=.{10}'-r'$0$1',结果只需要0.6秒!