bash子序列匹配加速
我想知道是否有一种简单的方法可以检查一个字符串是否是bash中另一个字符串的子序列,实际上是一个具有额外规则的子序列。我会解释的 “苹果”的一些子序列是“aple”、“al”、“pp”和“ale”。我想得到的子序列有一个额外的规则,就是那些以与字符串相同的字母开始和结束的序列,所以只有“aple”和“ale”符合我的要求 我制作了以下程序:bash子序列匹配加速,bash,performance,subsequence,Bash,Performance,Subsequence,我想知道是否有一种简单的方法可以检查一个字符串是否是bash中另一个字符串的子序列,实际上是一个具有额外规则的子序列。我会解释的 “苹果”的一些子序列是“aple”、“al”、“pp”和“ale”。我想得到的子序列有一个额外的规则,就是那些以与字符串相同的字母开始和结束的序列,所以只有“aple”和“ale”符合我的要求 我制作了以下程序: #!/bin/bash while read line do search=$(echo "$line" | tr -s 'A-Za-z' | se
#!/bin/bash
while read line
do
search=$(echo "$line" | tr -s 'A-Za-z' | sed 's/./\.\*&/g;s/^\.\*//' )
expr match "$1" "$search" >/dev/null && echo "$line"
done
其执行如下:
./program.sh greogdgedlqfe < words.txt
/program.sh greogdgedlqfe
这个程序可以工作,但速度很慢
它获取文件的每一行,将其修改为正则表达式,然后检查它们是否匹配,然后打印原始行。例如:
其中一行有单词google
$search变为g.*o.*g.*l.*e(重复的字母被压缩,额外规则)
然后我们用给定的参数检查这个表达式,如果它匹配,我们打印行:google
这很好,但是当words.txt文件太大时,这个程序会变得太慢。我如何加速我的程序,可能是通过更快的匹配子序列
在可能的Kamilcuk解决方案后编辑
该解决方案返回字符串“qwertyuihgfcvbnhjk”的quick、quin、qwerty,并且只返回quick,因此它几乎是正确的,但还不完全正确。
bash
不需要使用expr
(外部程序)进行正则表达式匹配;它提供对系统库的内置访问
#!/bin/bash
while read line
do
search=$(echo "$line" | tr -s 'A-Za-z' | sed 's/./\.\*&/g;s/^\.\*//' )
[[ $1 =~ $search ]] && echo "$line"
done
bash
不需要使用expr
(外部程序)进行正则表达式匹配;它提供对系统库的内置访问
#!/bin/bash
while read line
do
search=$(echo "$line" | tr -s 'A-Za-z' | sed 's/./\.\*&/g;s/^\.\*//' )
[[ $1 =~ $search ]] && echo "$line"
done
您可以使用模式而不是正则表达式。只需在每个单词的每个字母后插入星号(最后一个字母除外),并使用正常模式匹配
#!/bin/bash
while read line
do
pattern=""
for ((i=${#line}-1 ; i>=0 ; --i)) ; do
pattern="${line:i:1}*"$pattern
done
pattern=${pattern%'*'}
if [[ "$1" == $pattern ]] ; then
echo "$line"
fi
done
您可以使用模式而不是正则表达式。只需在每个单词的每个字母后插入星号(最后一个字母除外),并使用正常模式匹配
#!/bin/bash
while read line
do
pattern=""
for ((i=${#line}-1 ; i>=0 ; --i)) ; do
pattern="${line:i:1}*"$pattern
done
pattern=${pattern%'*'}
if [[ "$1" == $pattern ]] ; then
echo "$line"
fi
done
试着这样做:
grep -x "$(<<<"$1" tr -s 'A-Za-z' | sed 's/./&*/g;s/\*$//;s/\*//1')" words.txt
对于set--greogdgedlqfe
它只输出google
如果我没弄错的话,苹果公司的“后续”就是一切符合ap*l*e
的东西
像这样尝试:
grep -x "$(<<<"$1" tr -s 'A-Za-z' | sed 's/./&*/g;s/\*$//;s/\*//1')" words.txt
对于set--greogdgedlqfe
它只输出google
如果我没弄错的话,苹果公司的“后续”就是一切符合ap*l*e
的东西
使用regexp很难击败
perl
性能
性能的关键是避免分叉额外的进程。这里介绍的大多数bash解决方案(基于KamilCukgrep
的解决方案除外,它并不总是正确的)都需要多次调用sed、tr等。Perl的性能将优于这些解决方案。即使可以实现一个纯bash解决方案(使用bash-RE,patterns),当单词列表的大小很大时,Perl的性能也可能优于它
考虑program.pl appl
#! /usr/bin/perl
use strict ;
my $word = shift @ARGV ;
while ( <> ) {
chomp ;
my $p = $_ ;
tr/A-Za-z//s ;
s/(.)/.*$1/g ;
s/^\.\*// ;
print $p, "\n" if $word =~ "^$_\$" ;
} ;
#/usr/bin/perl
严格使用;
my$word=shift@ARGV;
而(){
咀嚼;
我的$p=$\;
tr/A-Za-z//s;
每克1美元;
s/^\.\*/;
打印$p,“\n”如果$word=~”^$\u\$”;
} ;
更新1:KamilCuk解决方案+修复的Perl实现。
在进行了一些小的修改之后,我相信可以使用基于grep的解决方案中的思想来创建一个速度更快的Perl程序。它创建一个REGEXP,并测试单词列表文件中的每个单词。我认为这是Perl的最佳选择
#! /usr/bin/perl
use strict ;
$_ = shift @ARGV ;
tr/A-Za-z//s ;
s/(.)/$1*/g ;
s/\*// ;
s/\*$// ;
my $re = "^$_\$" ;
print "RE=$re\n" ;
while ( <> ) {
chomp ;
print $_, "\n" if /$re/ ;
} ;
#/usr/bin/perl
严格使用;
$\ux=shift@ARGV;
tr/A-Za-z//s;
s/()/$1*/g;
s/\*/;
s/\*$/;
my$re=“^$\u\$”;
打印“RE=$RE\n”;
而(){
咀嚼;
如果/$re/,则打印“$\n”;
} ;
使用regexp很难打败perl
性能
性能的关键是避免分叉额外的进程。这里介绍的大多数bash解决方案(基于KamilCukgrep
的解决方案除外,它并不总是正确的)都需要多次调用sed、tr等。Perl的性能将优于这些解决方案。即使可以实现一个纯bash解决方案(使用bash-RE,patterns),当单词列表的大小很大时,Perl的性能也可能优于它
考虑program.pl appl
#! /usr/bin/perl
use strict ;
my $word = shift @ARGV ;
while ( <> ) {
chomp ;
my $p = $_ ;
tr/A-Za-z//s ;
s/(.)/.*$1/g ;
s/^\.\*// ;
print $p, "\n" if $word =~ "^$_\$" ;
} ;
#/usr/bin/perl
严格使用;
my$word=shift@ARGV;
而(){
咀嚼;
我的$p=$\;
tr/A-Za-z//s;
每克1美元;
s/^\.\*/;
打印$p,“\n”如果$word=~”^$\u\$”;
} ;
更新1:KamilCuk解决方案+修复的Perl实现。
在进行了一些小的修改之后,我相信可以使用基于grep的解决方案中的思想来创建一个速度更快的Perl程序。它创建一个REGEXP,并测试单词列表文件中的每个单词。我认为这是Perl的最佳选择
#! /usr/bin/perl
use strict ;
$_ = shift @ARGV ;
tr/A-Za-z//s ;
s/(.)/$1*/g ;
s/\*// ;
s/\*$// ;
my $re = "^$_\$" ;
print "RE=$re\n" ;
while ( <> ) {
chomp ;
print $_, "\n" if /$re/ ;
} ;
#/usr/bin/perl
严格使用;
$\ux=shift@ARGV;
tr/A-Za-z//s;
s/()/$1*/g;
s/\*/;
s/\*$/;
my$re=“^$\u\$”;
打印“RE=$RE\n”;
而(){
咀嚼;
如果/$re/,则打印“$\n”;
} ;
您能否发布words.txt的一些摘录和示例输出。我无法测试您的脚本,对于某些输入,一些匹配和不匹配的单词将非常有用。apppppppple
是apple
的子序列吗?因为您的脚本将与apple
匹配。如果我理解正确,只有apple
的4个有效子序列:ae
ale
ape
。是吗?是的,但是apppe在我的程序中也会匹配,这是故意的。Och?那么apple
也是苹果的后继产品吗?“后续”看起来不像“子序列”,更像是一个扩展。因此,子序列就是与正则表达式匹配的任何东西,正则表达式由一个单词的字母组成,带有*