Perl:最快的比赛?
Perl: Fastest match of anything?
我想在不使用 /s 的情况下执行此操作:
(?:.|\n)+
我希望它快点。
它是一个更大的正则表达式的一部分,这就是我不能使用 /s 的原因。我测试过:
perl -pe 's/(?:.|\n)+//' # 30 MBytes/s
perl -pe 's/[^7]+//' # 124 MBytes/s
它们没有 /s 快:
perl -pe 's/.+//s' # 164 MBytes/s
我能以某种方式获得与 /s 相同的速度吗?
编辑:
perl -pe 's/(?s).+(?-s)//' # 162 MBytes/s
perl -pe 's/[\d\D]+//' # 162 MBytes/s
perl -pe 's/[\s\S]+//' # 161 MBytes/s
这些都是不错的选择。谢谢
您不需要使用任何解决方法。
您可以使用内联修饰符标志,(?s)
启用点以跨行匹配,(?-s)
禁用此效果。
例如:
(?s).*PATTERN(?-s).*
第一个 .*
匹配任何文本,最后一个 .*
只匹配到一行的结尾。
您还可以使用修饰符组:
(?s:.*)PATTERN(?-s:.*)
更多内容见Extended Patterns。
您可以使用 (?s:PATTERN)
为括号中的子模式启用 /s
。
(?s:.)+
或
(?s:.+)
例如,
$ perl -M5.010 -e'
say /^.(?s:.).\z/ ? "match" : "no match"
for "\n\n\n", "A\n\n", "\n\nA", "A\nA";
'
no match
no match
no match
match
.
与 /s
和 (?s:.)
之间没有区别,因此您将获得完全相同的性能。
$ perl -Mre=debug -e'qr/(?s:.)/'
Compiling REx "(?s:.)"
Final program:
1: SANY (2)
2: END (0)
minlen 1
Freeing REx: "(?s:.)"
$ perl -Mre=debug -e'qr/./s'
Compiling REx "."
Final program:
1: SANY (2)
2: END (0)
minlen 1
Freeing REx: "."
相对于其他解决方案的优势:
(?s:.)
恢复 s
标志状态,而 (?s).(?-s)
将其关闭。
(?s:.)
比 (?s).(?-s)
. 短一点
(?s:.)
不长于 [\s\S]
和 [\d\D]
.
(?s:.)
不是像 [\s\S]
和 [\d\D]
那样的解决方法。
也就是说,(?s:.)
、(?s).(?-s)
、[\s\S]
和 [\d\D]
都会生成完全相同的正则表达式程序(自 5.24 起),因此它们都会执行一模一样。
如果我创建一个 98MB 的文件:
$ dd bs=1024 count=100000 </dev/urandom >file
100000+0 records in
100000+0 records out
102400000 bytes transferred in 0.558640 secs (183302305 bytes/sec)
现在比较一些方法:
time perl -0777 -lne 's/(?:.|\n)+//' file
real 0m1.957s
user 0m1.902s
sys 0m0.050s
time perl -0777 -lne 's/[^7]+//' file
real 0m0.130s
user 0m0.082s
sys 0m0.046s
time perl -0777 -lne 's/[\s\S]+//' file
real 0m0.065s
user 0m0.022s
sys 0m0.041s
time perl -0777 -lne 's/.+//s' file
real 0m0.064s
user 0m0.022s
sys 0m0.038s
如您所见,[\s\S]
的字符class从5.24开始优化为/./s
。
$ perl -Mre=debug -e'qr/./s'
Compiling REx "."
Final program:
1: SANY (2)
2: END (0)
minlen 1
Freeing REx: "."
$ perl -Mre=debug -e'qr/[\s\S]/'
Compiling REx "[\s\S]"
Final program:
1: SANY (2)
2: END (0)
minlen 1
Freeing REx: "[\s\S]"
我想在不使用 /s 的情况下执行此操作:
(?:.|\n)+
我希望它快点。
它是一个更大的正则表达式的一部分,这就是我不能使用 /s 的原因。我测试过:
perl -pe 's/(?:.|\n)+//' # 30 MBytes/s
perl -pe 's/[^7]+//' # 124 MBytes/s
它们没有 /s 快:
perl -pe 's/.+//s' # 164 MBytes/s
我能以某种方式获得与 /s 相同的速度吗?
编辑:
perl -pe 's/(?s).+(?-s)//' # 162 MBytes/s
perl -pe 's/[\d\D]+//' # 162 MBytes/s
perl -pe 's/[\s\S]+//' # 161 MBytes/s
这些都是不错的选择。谢谢
您不需要使用任何解决方法。
您可以使用内联修饰符标志,(?s)
启用点以跨行匹配,(?-s)
禁用此效果。
例如:
(?s).*PATTERN(?-s).*
第一个 .*
匹配任何文本,最后一个 .*
只匹配到一行的结尾。
您还可以使用修饰符组:
(?s:.*)PATTERN(?-s:.*)
更多内容见Extended Patterns。
您可以使用 (?s:PATTERN)
为括号中的子模式启用 /s
。
(?s:.)+
或
(?s:.+)
例如,
$ perl -M5.010 -e'
say /^.(?s:.).\z/ ? "match" : "no match"
for "\n\n\n", "A\n\n", "\n\nA", "A\nA";
'
no match
no match
no match
match
.
与 /s
和 (?s:.)
之间没有区别,因此您将获得完全相同的性能。
$ perl -Mre=debug -e'qr/(?s:.)/'
Compiling REx "(?s:.)"
Final program:
1: SANY (2)
2: END (0)
minlen 1
Freeing REx: "(?s:.)"
$ perl -Mre=debug -e'qr/./s'
Compiling REx "."
Final program:
1: SANY (2)
2: END (0)
minlen 1
Freeing REx: "."
相对于其他解决方案的优势:
(?s:.)
恢复s
标志状态,而(?s).(?-s)
将其关闭。(?s:.)
比(?s).(?-s)
. 短一点
(?s:.)
不长于[\s\S]
和[\d\D]
.(?s:.)
不是像[\s\S]
和[\d\D]
那样的解决方法。
也就是说,(?s:.)
、(?s).(?-s)
、[\s\S]
和 [\d\D]
都会生成完全相同的正则表达式程序(自 5.24 起),因此它们都会执行一模一样。
如果我创建一个 98MB 的文件:
$ dd bs=1024 count=100000 </dev/urandom >file
100000+0 records in
100000+0 records out
102400000 bytes transferred in 0.558640 secs (183302305 bytes/sec)
现在比较一些方法:
time perl -0777 -lne 's/(?:.|\n)+//' file
real 0m1.957s
user 0m1.902s
sys 0m0.050s
time perl -0777 -lne 's/[^7]+//' file
real 0m0.130s
user 0m0.082s
sys 0m0.046s
time perl -0777 -lne 's/[\s\S]+//' file
real 0m0.065s
user 0m0.022s
sys 0m0.041s
time perl -0777 -lne 's/.+//s' file
real 0m0.064s
user 0m0.022s
sys 0m0.038s
如您所见,[\s\S]
的字符class从5.24开始优化为/./s
。
$ perl -Mre=debug -e'qr/./s'
Compiling REx "."
Final program:
1: SANY (2)
2: END (0)
minlen 1
Freeing REx: "."
$ perl -Mre=debug -e'qr/[\s\S]/'
Compiling REx "[\s\S]"
Final program:
1: SANY (2)
2: END (0)
minlen 1
Freeing REx: "[\s\S]"