Compare commits

..

276 Commits
0.0.7 ... 0.2.3

Author SHA1 Message Date
Andrew Gallant
d8712daf27 0.2.3 2016-10-11 19:44:54 -04:00
Andrew Gallant
7cbbef019f changelog 0.2.3 2016-10-11 19:44:50 -04:00
Andrew Gallant
4d29d886e5 Merge pull request #168 from durka/doc-threads
clarify docs for --threads
2016-10-11 19:27:11 -04:00
Andrew Gallant
247a9398f4 Switch to thread_local crate in lieu of thread_local!.
This is to work around a bug where using a thread_local! was causing
a segfault on macos.

Fixes #164.
2016-10-11 18:23:49 -04:00
Alex Burka
4c3025ab1c clarify docs for --threads 2016-10-11 17:32:51 -04:00
Andrew Gallant
4981991a6e 0.2.2 2016-10-10 22:24:36 -04:00
Andrew Gallant
51440f59cd Don't include HomebrewFormula in crate. 2016-10-10 22:24:28 -04:00
Andrew Gallant
7b8a8d77d0 changelog 0.2.2 2016-10-10 22:18:21 -04:00
Andrew Gallant
4737326ed3 Update regex-syntax for bug fix.
The bug fix was in expression pretty printing. ripgrep parses the regex
into an AST and may do some modifications to it, which requires the
ability to go from string -> AST -> string' -> AST' where string == string'
implies AST == AST'.

Also, add a regression test for the specific regex that tripped the bug.

Fixes #156.
2016-10-10 22:04:29 -04:00
Andrew Gallant
a3537aa32a Update darwin cfg attributes. 2016-10-10 21:48:47 -04:00
Andrew Gallant
d3e118a786 Fix debug expression statement. 2016-10-10 21:48:34 -04:00
Andrew Gallant
4e52059ad6 Disable regression_131 test on darwin.
It's not clear why it's failing. Maybe it doesn't permit certain
characters in file paths?
2016-10-10 21:03:11 -04:00
Andrew Gallant
60c016c243 Fix docopt usage string. Gah. 2016-10-10 20:49:39 -04:00
Andrew Gallant
4665128f25 Clarify documentation for --replace.
Also add a minor clarification for --type-add.

Fixes #147
2016-10-10 20:19:45 -04:00
Andrew Gallant
dde5bd5a80 globset-0.1.0 2016-10-10 20:07:13 -04:00
Andrew Gallant
762ad44f71 add version marker 2016-10-10 20:06:35 -04:00
Andrew Gallant
705386934d Fill in globset/Cargo.toml with more details. 2016-10-10 19:50:21 -04:00
Andrew Gallant
97bbc6ef11 Update appveyor to test subcrates. 2016-10-10 19:35:47 -04:00
Andrew Gallant
27a980c1bc Fix symlink test.
We attempt to run it on Windows, but I'm getting "access denied" errors
when trying to create a file symlink. So we disable the test on Windows.
2016-10-10 19:34:57 -04:00
Andrew Gallant
e8645dc8ae style nits 2016-10-10 19:27:12 -04:00
Andrew Gallant
e96d93034a Finish overhaul of glob matching.
This commit completes the initial move of glob matching to an external
crate, including fixing up cross platform support, polishing the
external crate for others to use and fixing a number of bugs in the
process.

Fixes #87, #127, #131
2016-10-10 19:24:18 -04:00
Andrew Gallant
bc5accc035 Merge pull request #161 from moshen/update-homebrew-readme
Update Homebrew instructions in the README
2016-10-10 19:11:50 -04:00
Andrew Gallant
c9d0ca8257 Merge pull request #157 from CannedYerins/follow-explicit-args
Always follow symlinks on explicit file arguments
2016-10-10 19:11:10 -04:00
Andrew Gallant
45fe4aab96 Merge pull request #155 from theamazingfedex/adding-extra-md-filetype
Adding extra .md filetype for ease of access to Markdown filetypes
2016-10-10 19:09:15 -04:00
Andrew Gallant
97f981fbcb Merge pull request #154 from theamazingfedex/adding-spark-filetype
Adding .spark filetype
2016-10-10 19:08:20 -04:00
Andrew Gallant
59329dcc61 Merge pull request #153 from theamazingfedex/master
Adding .config filetype
2016-10-10 19:08:06 -04:00
Colin Kennedy
604da8eb86 Update Homebrew instructions in the README 2016-10-09 23:45:02 -05:00
Ian Kerins
1c964372ad Always follow symlinks on explicit file arguments. 2016-10-08 22:40:03 -04:00
Daniel Wood
50a961960e added extra .md filetype for ease of access 2016-10-07 14:37:29 -06:00
Daniel Wood
7481c5fe29 added .spark filetype 2016-10-07 14:35:20 -06:00
Daniel Wood
3ae37b0937 added .config filetype 2016-10-07 13:50:26 -06:00
Andrew Gallant
4ee6dbe422 Merge pull request #148 from munyari/patch-1
Change Arch Linux instructions
2016-10-05 09:53:17 -04:00
Panashe Fundira
cd4bdcf810 Change Arch Linux instructions
The `-Syu` flag will do a full system upgrade and then install the package, which is not necessarily the desired behavior. Only the `-S` flag is necessary to install a single package.
See https://wiki.archlinux.org/index.php/Pacman#Installing_specific_packages
https://wiki.archlinux.org/index.php/Pacman#Upgrading_packages
2016-10-05 08:26:19 -04:00
Andrew Gallant
175406df01 Refactor and test glob sets.
This commit goes a long way toward refactoring glob sets so that the
code is easier to maintain going forward. In particular, it makes the
literal optimizations that glob sets used a lot more structured and much
easier to extend. Tests have also been modified to include glob sets.

There's still a bit of polish work left to do before a release.

This also fixes the immediate issue where large gitignore files were
causing ripgrep to slow way down. While we don't technically fix it for
good, we're a lot better about reducing the number of regexes we
compile. In particular, if a gitignore file contains thousands of
patterns that can't be matched more simply using literals, then ripgrep
will slow down again. We could fix this for good by avoiding RegexSet if
the number of regexes grows too large.

Fixes #134.
2016-10-04 20:28:56 -04:00
Andrew Gallant
89811d43d4 Merge pull request #146 from samuelcolvin/add-jinja-type
add jinja type for *.jinja and *.jinja2
2016-10-04 08:25:22 -04:00
Samuel Colvin
f0053682c0 add jinja type for *.jinja and *.jinja2 2016-10-04 13:15:31 +01:00
Andrew Gallant
35045d6105 Merge pull request #143 from moshen/change-brew-formula-name
Fix brew formula name to not conflict with core
2016-10-04 06:49:16 -04:00
Colin Kennedy
95f552fc06 Fix brew formula name to not conflict with core
Since the homebrew-core formula was accepted, we should differentiate
the prebuilt formula available in this tap
2016-10-03 22:30:26 -05:00
Andrew Gallant
48353bea17 Merge pull request #144 from bitshifter/dotcmake
Added *.cmake extension to cmake file type.
2016-10-03 20:51:05 -04:00
Cameron Hart
703d5b558e Added *.cmake extension to cmake file type. 2016-10-04 11:28:49 +11:00
Andrew Gallant
47efea234f Remove i686-darwin.
Apparently 32 bit Mac CPUs are really old at this point. Also, it has
been causing CI to fail lately. It's not worth it.
2016-10-03 17:16:28 -04:00
Andrew Gallant
ca0d8998a2 Merge pull request #139 from moshen/make-a-tap
Make the repo a Homebrew Tap
2016-10-03 17:14:09 -04:00
Andrew Gallant
fdf24317ac Move glob implementation to new crate.
It is isolated and complex enough that it deserves attention all on its
own. It's also eminently reusable.
2016-09-30 19:42:41 -04:00
Andrew Gallant
b9d5f22a4d Stopgap measure for projects with huge gitignore files.
This helps #134 by avoiding a slow regex execution path, but doesn't
actually fix the problem. Namely, we've gone from "so slow I'm not going
to keep waiting for rg to finish" to "wow that was slow but at least it
finished before I lost my patience."
2016-09-30 19:29:52 -04:00
Colin Kennedy
67bb4f040f Make the repo a Homebrew Tap 2016-09-30 12:51:37 -05:00
Andrew Gallant
cee2f09a6d Merge pull request #121 from lilydjwg/master
if --color always, always print with color, even when --vimgrep is given
2016-09-29 16:49:44 -04:00
Andrew Gallant
ced777e91f Merge pull request #133 from akien-mga/pr-appveyor
AppVeyor: Change release description to fit Travis binaries
2016-09-29 09:35:44 -04:00
Rémi Verschelde
e9d9083898 AppVeyor: Change release description to fit Travis binaries 2016-09-29 15:29:59 +02:00
Andrew Gallant
46dff8f4be Be better with short circuiting with --quiet.
It didn't make sense for --quiet to be part of the printer, because --quiet
doesn't just mean "don't print," it also means, "stop after the first
match is found." This needs to be wired all the way up through directory
traversal, and it also needs to cause all of the search workers to quit
as well. We do it with an atomic that is only checked with --quiet is
given.

Fixes #116.
2016-09-28 20:50:50 -04:00
Andrew Gallant
7aa6e87952 clarify 2016-09-28 16:47:10 -04:00
Andrew Gallant
925d0db9f0 Add -s/--case-sensitive flag.
This flag overrides both --smart-case and --ignore-case.

Closes #124.
2016-09-28 16:32:29 -04:00
Andrew Gallant
316ffd87b3 bump docopt to 0.6.86 2016-09-28 15:56:59 -04:00
依云
5943b1effe if --color always, always print with color, even when --vimgrep is given 2016-09-28 20:10:07 +08:00
Andrew Gallant
c42f97b4da Merge pull request #122 from lilydjwg/color-filename
colorize filepath at the beginning of line too
2016-09-28 07:06:34 -04:00
依云
0d9bba7816 colorize filepath at the beginning of line too 2016-09-28 11:54:43 +08:00
Andrew Gallant
3550f2e29a Merge pull request #111 from gsquire/max-depth
Max depth option
2016-09-27 19:46:29 -04:00
Garrett Squire
babe80d498 add a max-depth option for directory traversal
CR and add integration test
2016-09-27 16:14:53 -07:00
Andrew Gallant
3e892a7a80 Correct example with --type-add.
Fixes #118.
2016-09-27 18:35:06 -04:00
Andrew Gallant
1df3f0b793 Merge pull request #114 from cetra3/colorChoice
Create Colour Choice struct to adjust colours depending on platform
2016-09-27 09:43:47 -04:00
cetra3
b3935935cb Add colour choice 2016-09-27 22:51:07 +09:30
Andrew Gallant
67abbf6f22 Merge pull request #115 from nickstenning/update-brew-hashes
Update brew 0.2.1 package hashes
2016-09-27 07:01:27 -04:00
Nick Stenning
7b9f7d7dc6 Update brew 0.2.1 package hashes 2016-09-27 12:01:22 +02:00
Andrew Gallant
7ab29a91d0 fix use of --type-add 2016-09-26 20:58:28 -04:00
Andrew Gallant
9fa38c6232 brew 0.2.1 2016-09-26 20:42:12 -04:00
Andrew Gallant
de79be2db2 0.2.1 2016-09-26 20:02:58 -04:00
Andrew Gallant
416b69bae5 changelog 0.2.1 2016-09-26 20:02:47 -04:00
Andrew Gallant
3e78fce3a3 Don't print empty lines in single threaded mode.
Fixes #99.
2016-09-26 19:57:23 -04:00
Andrew Gallant
7a3fd1f23f Add a --null flag.
This flag causes a NUL byte to follow any file path in ripgrep's output.

Closes #89.
2016-09-26 19:21:17 -04:00
Andrew Gallant
d306403440 Fix an off-by-one error with --column.
Fixes #105.
2016-09-26 19:09:59 -04:00
Andrew Gallant
ebabe1df6a Merge branch 'gitignore_blank_lines' 2016-09-26 18:55:43 -04:00
Andrew Gallant
f27aa3ff6f Add regression test.
Fixes #106.
2016-09-26 18:55:26 -04:00
Tom Jackson
20ccd441f2 Allow (and ignore) whitespace-only lines in .gitignore files
Git considers these to be blank lines.
2016-09-26 18:52:57 -04:00
Andrew Gallant
104d740f76 Don't quit if opening a file fails.
This was already working correctly in multithreaded mode, but in single
threaded mode, a file failing to open caused search to stop. That's bad.

Fixes #98.
2016-09-26 18:44:19 -04:00
Andrew Gallant
2da0eab2b8 Don't initialize ignores for file arguments.
We'll never use them, so it's wasted effort.
2016-09-26 18:44:19 -04:00
Andrew Gallant
b8c7864a02 Merge pull request #107 from kaushalmodi/add-systemverilog-type
Add SystemVerilog (SV) type
2016-09-26 16:54:49 -04:00
Kaushal Modi
ec26995655 Add SystemVerilog (SV) type 2016-09-26 15:24:35 -04:00
Andrew Gallant
a41235a3b5 Merge pull request #100 from emlyn/patch-1
Recognise cljc and cljx extensions as Clojure(script)
2016-09-26 08:59:59 -04:00
Emlyn Corrin
1a91b900e7 Clojure files can also end in cljc or cljx
(see https://github.com/clojure/clojurescript/wiki/Using-cljc)
2016-09-26 09:53:46 +01:00
Andrew Gallant
2b15832655 update brew formula to 0.2.0 2016-09-25 22:50:50 -04:00
Andrew Gallant
b1c52b52d6 0.2.0 2016-09-25 22:32:14 -04:00
Andrew Gallant
109bc3f78e bump grep to 0.1.3 2016-09-25 22:30:17 -04:00
Andrew Gallant
b62195b33f grep 0.1.3 2016-09-25 22:29:35 -04:00
Andrew Gallant
baebfd7add changelog 0.2.0 2016-09-25 22:27:58 -04:00
Andrew Gallant
19e405e5c5 fix windows 2016-09-25 21:48:01 -04:00
Andrew Gallant
f85822266f Don't use an intermediate buffer when --threads=1.
Fixes #8
2016-09-25 21:27:17 -04:00
Andrew Gallant
b034b77798 Don't replace NUL bytes when searching binary files as text.
This was a result of misinterpreting a feature in grep where NUL bytes
are replaced with \n. The primary reason for doing this is to avoid
excessive memory usage on truly binary data. However, grep only does this
when searching binary files as if they were binary, and which only reports
whether the file matched or not. When grep is told to search binary data
as text (the -a/--text flag), then it doesn't do any replacement so we
shouldn't either.

In general, this makes sense, because the user is essentially asserting
that a particular file that looks like binary is actually text. In that
case, we shouldn't try to replace any NUL bytes.

ripgrep doesn't actually support searching binary data for whether it
matches or not, so we don't actually need the replace_buf function.
However, it does seem like a potentially useful feature.
2016-09-25 21:26:49 -04:00
Andrew Gallant
278e1168bf Make printing paths a bit faster.
It seems silly, but on *nix, we can just dump the bytes of the path
straight to the terminal. There's no need to do a UTF-8 check, which
can be costly when printing lots of matches.
2016-09-25 21:23:26 -04:00
Andrew Gallant
6a8051b258 Don't union inner literals of repetitions.
If we do, this results in extracting `foofoofoo` from `(\wfoo){3}`,
which is wrong. This does prevent us from extracting `foofoofoo` from
`foo{3}`, which is unfortunate, but we miss plenty of other stuff too.
Literal extracting needs a good rethink (all the way down into the regex
engine).

Fixes #93
2016-09-25 20:10:28 -04:00
Andrew Gallant
a13ac3e3d4 On Windows, always consider stdin to be a tty.
This means that `rg pat < file` won't do the expected thing and search
`fil`. Instead, it will recursively search the current directory for `pat`.
This isn't ideal, but is better than the previous behavior, which was to
wait for stdin when running `rg pat`, given the appearance of hanging
forever. The former is an important use case, but the latter is the
*central* use case of ripgrep, so we should make that work.

`rg` can still be used to search stdin on Windows, it just needs to be
done explicitly. e.g., `rg pat - < file` will search for `pat` in `file`.

Fixes #19
2016-09-25 20:00:29 -04:00
Andrew Gallant
a72467996b Fix Windows compilation error. 2016-09-25 20:00:29 -04:00
Andrew Gallant
9395076468 Merge pull request #92 from svenstaro/patch-1
ripgrep is now in [community]
2016-09-25 18:50:03 -04:00
Sven-Hendrik Haase
a12c63957b ripgrep is now in [community]
The README should reflect that.
2016-09-26 00:48:41 +02:00
Andrew Gallant
982265af70 Move --files-with-matches to less common options. 2016-09-25 18:32:41 -04:00
Andrew Gallant
ed94aedf27 Permit whitelisting hidden files in ignores.
Fixes #90
2016-09-25 18:31:41 -04:00
Andrew Gallant
fd5ae2f795 Add curly brace alternates to glob format.
Closes #80.
2016-09-25 17:28:23 -04:00
Andrew Gallant
3d6a39be06 Fix tests on Windows.
Mostly this is just using \\ instead of / in paths reported by the OS.
2016-09-25 15:45:51 -04:00
Andrew Gallant
e7839f2200 Merge pull request #71 from catchmrbharath/issue46
[Fixes #46] Use 1 less worker thread than number of threads
2016-09-25 15:02:38 -04:00
Andrew Gallant
9dc5464c84 Stop after first match is found with --quiet.
Fixes #77.
2016-09-25 15:01:29 -04:00
Andrew Gallant
95edcd4d3a Merge pull request #42 from andschwa/files-with-matches
Files with matches
2016-09-25 14:53:31 -04:00
Andrew Gallant
d97f404970 Stupid docopt.
It thinks `--type-clear is` is a flag spec.
2016-09-25 14:47:35 -04:00
Andrew Gallant
b2bbd46178 Clarify documentation of --type-add.
This explains it a bit more based on end user feedback. We also fix
the example, which was wrong.

Fixes #82.
2016-09-25 14:37:01 -04:00
Andrew Gallant
82542df5cb Merge pull request #84 from martinlindhe/ts
Add ts type for typescript
2016-09-25 11:33:11 -04:00
Martin Lindhe
e4329037aa Add ts type for typescript 2016-09-25 17:16:15 +02:00
Andrew Gallant
ab0d1c1c79 Be more conservative with stdin.
If no paths are given to ripgrep, only read from stdin if it's a file or
a FIFO. In particular, if something like `rg foo < /dev/null` is used,
then don't try to read from stdin.

Fixes #35, #81
2016-09-25 11:14:54 -04:00
Andrew Gallant
2015c56e8d Merge pull request #62 from martinlindhe/js-wc
--type js: include more extensions
2016-09-25 11:10:47 -04:00
Martin Lindhe
23ad8b989d --type js: include more extensions 2016-09-25 17:06:13 +02:00
Andrew Schwartzmeyer
a8f3d9e87e Add --files-with-matches flag.
Closes #26.

Acts like --count but emits only the paths of files with matches,
suitable for piping to xargs. Both mmap and no-mmap searches terminate
after the first match is found. Documentation updated and tests added.
2016-09-24 21:40:17 -07:00
Bharath M R
9f1aae64f8 [Fixes #46] Use 1 less worker thread than number of threads
The main thread does directory traversal. Hence
number of threads = main Thread + number of worker threads.
We should have atleast one worker thread.
2016-09-24 19:48:26 -07:00
Andrew Gallant
1595f0faf5 Add --smart-case.
It does what it says on the tin.

Closes #70.
2016-09-24 21:51:04 -04:00
Andrew Gallant
8eeb0c0b60 Add --no-ignore-vcs flag.
This flag will respect .ignore but not .gitignore.

Closes #68.
2016-09-24 21:31:24 -04:00
Andrew Gallant
423f2a1927 Permit options with --help/--version.
Fixes #47.
2016-09-24 21:13:24 -04:00
Andrew Gallant
4b5e789a2a Strip trailing whitespace in gitignore patterns.
Fixes #38.
2016-09-24 20:56:24 -04:00
Andrew Gallant
37b731a048 Update brew package to 0.1.17.
Closes #58, Fixes #13
2016-09-24 20:51:07 -04:00
Andrew Gallant
a44735aa87 Tweak memory maps on darwin.
Namely, don't automatically pick memory maps on darwin, ever. They
appear slower than standard read calls.

Closes #36.
2016-09-24 20:48:05 -04:00
Andrew Gallant
6b2efd4d88 If a file is empty, still try to search it.
Files like /proc/cpuinfo will advertise themselves as a normal file with
size 0. Normally, this isn't a problem, but if ripgrep decides to use a
memory map, it skipped searching if the file was empty since it's an error
to memory map an empty file. Instead of returning 0, we should just fall
back to standard read calls.

Fixes #55.
2016-09-24 20:45:06 -04:00
Andrew Gallant
c8227e0cf3 Don't ignore first path when using --files.
This is a docopt oddity, but probably not a bug. If --files is given,
then just interpret the pattern (if not empty) as the first file path.

Fixes #64.
2016-09-24 20:22:02 -04:00
Andrew Gallant
b941c10b90 Fix directory whitelisting.
There was a bug in the translation from a gitignore pattern to a standard
glob where `!/dir` wasn't being interpreted as an absolute path.

Fixes #67.
2016-09-24 20:10:30 -04:00
Andrew Gallant
872a107658 Fix whitelisting precedence.
Once a file is known to be whitelisted, we shouldn't check any ancestor
gitignores.
2016-09-24 20:09:29 -04:00
Andrew Gallant
71ad9bf393 Fix trailing recursive globs in gitignore.
A standard glob of `foo/**` will match `foo`, but gitignore semantics
specify that `foo/**` should only match the contents of `foo` and not
`foo` itself. We capture those semantics by translating `foo/**` to
`foo/**/*`.

Fixes #30.
2016-09-24 19:44:06 -04:00
Andrew Gallant
f733e9ebe4 Fix typo.
Thanks @dmit!
2016-09-24 19:43:01 -04:00
Andrew Gallant
ce85df1d2e Clarify what rg does in --help.
Fixes #24.
2016-09-24 19:26:28 -04:00
Andrew Gallant
a6e3cab65a Add --no-filename flag.
When this flag is set, a filename is never shown for a match.

Closes #20
2016-09-24 19:24:24 -04:00
Andrew Gallant
7b860affbe Change the default output of --files to elide './'.
This is kind of a ticky-tack change. I do think ./ as a prefix is
reasonable default, *but* we strip ./ when showing search results, so it
does make sense to be consistent.

Fixes #21.
2016-09-24 19:18:48 -04:00
Andrew Gallant
af4dc78537 Update to docopt 0.6.85.
The new version won't panic if printing to stdout fails.

Fixes #22.
2016-09-24 19:14:19 -04:00
Andrew Gallant
9ce0484670 Clarify the documentation of the --type-* flags.
Fixes #15
2016-09-24 18:55:48 -04:00
Andrew Gallant
346bad7dfc Fix handling of absolute patterns in parent gitignore files.
If a gitignore file in a *parent* directory is used, then it must be
matched relative to the directory it's in. ripgrep wasn't actually
adhering to this rule. Consider an example:

  .gitignore
  src
    llvm
      foo

Where `.gitignore` contains `/llvm/` and `foo` contains `test`. When
running `rg test` at the top-level directory, `foo` is correctly searched.
If you `cd` into `src` and re-run the same search, `foo` is ignored because
the `/llvm/` pattern is interpreted with respect to the current working
directory, which is wrong. The problem is that the path of `llvm` is
`./llvm`, which makes it look like it should match.

We fix this by rebuilding the directory path of each file when traversing
gitignores in parent directories. This does come with a small performance
hit.

Fixes #25.
2016-09-24 18:40:50 -04:00
Andrew Gallant
56fe93d343 Fix an absolute path name bug.
Namely, if a .gitignore inside a sub-directory has an absolute pattern,
e.g., `/foo/`, then we should match it relative to the directory containing
the .gitignore.
2016-09-24 17:31:24 -04:00
Andrew Gallant
155676b474 Fixes #43. 2016-09-24 16:34:34 -04:00
Andrew Gallant
a3fc4cdded Fix a bug in the translation from a gitignore pattern to a glob.
We were erroneously neglecting to prefix a pattern like `foo/`
with `**/` (to make `**/foo/`) because it had a slash in it. In fact, the
only reason to neglect a **/ prefix is if the pattern already starts
with **/, or if the pattern is absolute.

Fixes #16, #49, #50, #65
2016-09-24 16:29:25 -04:00
Andrew Gallant
3bec8f3f0a Impl Debug for IgnoreDir. 2016-09-24 16:29:25 -04:00
Andrew Gallant
3b37f12ec0 Merge pull request #69 from dloss/nim-filetype
Add support for the Nim programming language file type
2016-09-24 16:04:58 -04:00
Dirk Loss
a2ed677e03 Add support for the Nim programming language file type 2016-09-24 21:48:33 +02:00
Andrew Gallant
2fb9c3c42c Merge pull request #56 from chrisdoc/feature/swift-file-type
Add support for the Swift programming language file type
2016-09-24 14:34:06 -04:00
Andrew Gallant
447e1ba0e2 Merge pull request #66 from kontomondo/master
FSharp language file type
2016-09-24 14:33:01 -04:00
Konto Mondo
3b45059212 FSharp language file type 2016-09-24 10:30:30 -04:00
chrisdoc
f74078af5b Add support for the Swift programming language file type 2016-09-24 08:42:44 +02:00
Andrew Gallant
5ff9b2f2a2 Merge pull request #41 from BurntSushi/generic-ignore
Switch from .rgignore to .ignore.
2016-09-23 23:14:38 -04:00
Andrew Gallant
cc90511ab2 Switch from .rgignore to .ignore.
But don't actually remove support for .rgignore until the next semver
bump.

Note that this puts us in line with the silver searcher:
https://github.com/ggreer/the_silver_searcher/pull/974

Fixes #40
2016-09-23 22:44:33 -04:00
Andrew Gallant
f5d60a80a8 Merge pull request #28 from ledge23/patch-1
Add VB files to default type list
2016-09-23 22:33:12 -04:00
Andrew Gallant
6fa158f6d3 Merge pull request #29 from jimhester/r_extensions
Add a few more R relevant extensions
2016-09-23 22:32:10 -04:00
Andrew Gallant
ef6dea40ff Merge pull request #39 from JohnVillalovos/master
Prefer https:// over git://
2016-09-23 22:28:20 -04:00
John L. Villalovos
9035c6b7b3 Prefer https:// over git://
1) git is not a secure protocol and vulnerable to man-in-the-middle
   attacks.
2) git:// is a pain for users behind proxy servers :(

Change-Id: I1901bebbaf8f64b23b070dee8732a6fb13cbdfdd
2016-09-23 16:34:24 -07:00
Andrew Gallant
f5eb36baac Fixing VC++ wording and link.
Kudos to @retep998
2016-09-23 18:39:07 -04:00
Andrew Gallant
6367dd61ba Column numbers should start at 1.
ripgrep was documented to do 1-based indexing, so this is a bug and not
a breaking change.

Fixes #18
2016-09-23 17:11:09 -04:00
Jim Hester
98892de1c1 Add a few more R relevant extensions 2016-09-23 14:48:15 -04:00
Zack Schuster
273c14a45a Add VB files to default type list
Use-case: While not a vogue technology, VB is still a common file type taught in many university settings and used in many commercial settings. Working with VB files out-of-the-box would provide a lot of value to `ripgrep` users.

Example: I'm working on converting a legacy app to a modern infrastructure. The legacy app mixes CS and VB files liberally, so I always need to check both. For portability, it would be nice to just be able to ask for `-tcs -tvb` without registering with `--type-add` first.

Tests: I didn't notice any coverage aimed at this part of the code, but if I'm mistaken I'll amend the PR.
2016-09-23 11:44:53 -07:00
Andrew Gallant
b33e9cba69 0.1.17 2016-09-23 11:26:23 -04:00
Andrew Gallant
d5c045469b Don't use panic-on-abort.
We don't really care anyway, it was there as an experiment, and it seems
to be causing problems.

Fixes #14.
2016-09-23 11:25:46 -04:00
Andrew Gallant
0ce82403d4 Switch over to the real README. 2016-09-23 06:56:56 -04:00
Andrew Gallant
d2f95f6e59 bump PKGBUILD 2016-09-22 21:43:51 -04:00
Andrew Gallant
25c259112b 0.1.16 2016-09-22 21:32:41 -04:00
Andrew Gallant
dfebed6cbe Add --vimgrep flag.
The --vimgrep flag forces a line to be printed for every match, with
line and column numbers.
2016-09-22 21:32:38 -04:00
Andrew Gallant
9981e7883a fix wording 2016-09-22 20:37:10 -04:00
Andrew Gallant
8d202e4bcf bump PKGBUILD to 0.1.15 2016-09-22 20:33:48 -04:00
Andrew Gallant
14c194dbe1 Update brew formula.
We have a man page on OSX. Yay!
2016-09-22 20:07:43 -04:00
Andrew Gallant
d547b92d76 Add benchmarks from local machine. 2016-09-22 19:55:30 -04:00
Andrew Gallant
e5a9cd1b64 Remove old benchmark runs. 2016-09-22 19:29:10 -04:00
Andrew Gallant
2115774c6e 0.1.15 2016-09-22 19:20:11 -04:00
Andrew Gallant
9087154b74 add man page to build artifact 2016-09-22 19:20:06 -04:00
Andrew Gallant
bb4fd9ddce update brew formula to 0.1.14 2016-09-22 19:13:13 -04:00
Andrew Gallant
d772b21f3d Include man page in Archlinux package. 2016-09-22 18:17:46 -04:00
Andrew Gallant
1b14e245be 0.1.14 2016-09-22 17:48:49 -04:00
Andrew Gallant
49003e8488 Add man page. 2016-09-22 17:48:41 -04:00
Andrew Gallant
80c362623a add link to regex syntax docs 2016-09-22 16:38:52 -04:00
Andrew Gallant
c1c484d1a7 Add a rg (no mmap) benchmark.
This is added to the subtitle benchmark. The purpose is to demonstrate
how memory mapping a single file for search is faster.
2016-09-21 21:42:34 -04:00
Andrew Gallant
263e2b012f 0.1.13 2016-09-21 21:07:40 -04:00
Andrew Gallant
b80a986721 fix -uuu test on Windows 2016-09-21 21:07:36 -04:00
Andrew Gallant
8a91d3132f add note about other repos 2016-09-21 20:56:06 -04:00
Andrew Gallant
525d051172 0.1.12 2016-09-21 20:47:44 -04:00
Andrew Gallant
5a9883d27c Try to use memory maps more aggressively on Windows.
Some brief playing around suggests that it is faster.

However, it's probably slower in a VM. Let's prioritize native users.
2016-09-21 20:47:40 -04:00
Andrew Gallant
f462d092e7 Add Archlinux AUR package. 2016-09-21 20:19:29 -04:00
Andrew Gallant
fe84928c85 0.1.11 2016-09-21 19:37:37 -04:00
Andrew Gallant
f7eaf67fc3 grrr fix appveyor deployment filter 2016-09-21 19:37:34 -04:00
Andrew Gallant
c1c92e4fee 0.1.10 2016-09-21 19:27:16 -04:00
Andrew Gallant
5644bbe43a attempt to fix Windows build 2016-09-21 19:27:12 -04:00
Andrew Gallant
aeb3a5ba0f bump grep to 0.1.2 2016-09-21 19:16:28 -04:00
Andrew Gallant
24e14a0341 grep 0.1.2 2016-09-21 19:14:12 -04:00
Andrew Gallant
2a2b1506d4 Fix a performance bug where using -w could result in very bad performance.
The specific issue is that -w causes the regex to be wrapped in Unicode
word boundaries. Regrettably, Unicode word boundaries are the one thing
our regex engine can't handle well in the presence of non-ASCII text. We
work around its slowness by stripping word boundaries in some
circumstances, and using the resulting expression as a way to produce match
candidates that are then verified by the full original regex.

This doesn't fix all cases, but it should fix all cases where -w is used.
2016-09-21 19:12:07 -04:00
Andrew Gallant
4d6b3c727e Bump regex version. 2016-09-21 19:05:15 -04:00
Andrew Gallant
c2bf9e3d45 fix brew 2016-09-21 17:36:46 -04:00
Andrew Gallant
dad73b92eb Add brew. 2016-09-21 17:28:19 -04:00
Andrew Gallant
b0d8ff6f4a 0.1.9 2016-09-21 16:41:28 -04:00
Andrew Gallant
0263a401f6 0.1.8 2016-09-21 07:08:37 -04:00
Andrew Gallant
4cb1b9ccc0 typo 2016-09-20 22:18:46 -04:00
Andrew Gallant
6f80e2e126 clarify 2016-09-20 22:15:25 -04:00
Andrew Gallant
f9bff90842 0.1.7 2016-09-20 22:13:49 -04:00
Andrew Gallant
5af4ec0056 Remove GNU nightly build.
We should probably still test on it, but I'd prefer distributing exactly
one Linux binary. Since the musl build is a totally static executable,
we should prefer that.

(The right answer is to test on GNU nightly, but don't produce a release
artifact.)
2016-09-20 22:12:41 -04:00
Andrew Gallant
9e2f10b893 0.1.6 2016-09-20 20:25:51 -04:00
Andrew Gallant
69095cf5c3 Add an error message for catching a common failure mode.
If you're in a directory that has a parent .gitignore (like, your $HOME),
then it can cause ripgrep to simply not do anything depending on your
ignore rules.

There are probably other scenarios where ripgrep applies some filter that
an end user doesn't expect, so try to catch the worst case (when ripgrep
doesn't search anything).
2016-09-20 20:25:24 -04:00
Andrew Gallant
7402db7b43 Add "unrestricted" flag.
I don't like having multiple flags do the same thing, but -u, -uu and -uuu
are much easier to remember, particularly with -uuu meaning "search
everything."
2016-09-20 20:24:03 -04:00
Andrew Gallant
7698b60256 Add new benchmarks.
These benchmarks are exactly like the ones ran on 2016-09-17 with three
changes:

1. `pt` was added back to a few more benchmarks so that it appears any
   time `sift` appears.
2. Warmup iterations was bumped from 1 to 3.
3. Actual benchmark iterations were bumped from 3 to 10.

These benchmarks took around two hours to run.
2016-09-20 16:35:09 -04:00
Andrew Gallant
e7fb0fd267 0.1.5 2016-09-19 21:56:00 -04:00
Andrew Gallant
29b59074c7 add links 2016-09-18 19:05:16 -04:00
Andrew Gallant
ee5eb2d659 format 2016-09-18 19:03:02 -04:00
Andrew Gallant
bf8094344a add tool names 2016-09-18 19:02:34 -04:00
Andrew Gallant
a0819978aa update shield 2016-09-18 18:38:57 -04:00
Andrew Gallant
5b7c17e2fb clarify 2016-09-18 18:35:32 -04:00
Andrew Gallant
bf56b3bb8e clarify 2016-09-18 18:34:09 -04:00
Andrew Gallant
9299d84d41 format 2016-09-18 18:31:08 -04:00
Andrew Gallant
2cf1a08969 ripgrep 0.1.4 2016-09-18 18:19:02 -04:00
Andrew Gallant
665b6016e3 add file include/exclude example 2016-09-18 18:18:01 -04:00
Andrew Gallant
33231622f3 update draft 2016-09-18 01:36:47 -04:00
Andrew Gallant
919c5c7299 tweak 2016-09-17 17:37:55 -04:00
Andrew Gallant
f9bf1e4a22 draft 2016-09-17 17:36:54 -04:00
Andrew Gallant
f7ee914dd3 Add support for searching multiple patterns with -e.
Also, change -Q/--literal to -F/--fixed-strings because compatibility
with grep is probably better.
2016-09-17 16:55:58 -04:00
Andrew Gallant
0a63158a61 Fix error handling bug. 2016-09-17 15:17:48 -04:00
Andrew Gallant
6cb604f38f 0.1.3 2016-09-17 12:55:09 -04:00
Andrew Gallant
bfbbfbf979 fix windows build
Why isn't CI running on each push? It seems to only be running on tagged
commits.
2016-09-17 12:54:46 -04:00
Andrew Gallant
403ba5fdc8 Add Ubuntu 16.04 benchmark runs 2016-09-17 12:41:10 -04:00
Andrew Gallant
8f87a4e8ac 0.1.2 2016-09-17 11:36:11 -04:00
Andrew Gallant
d27d3e675f bump grep 2016-09-17 11:34:27 -04:00
Andrew Gallant
bf5d873099 grep 0.1.1 2016-09-17 11:32:47 -04:00
Andrew Gallant
bc9d12c4c8 Improve ergonomics of benchsuite.
The runner now detects if commands exist and permits running incomplete
benchmarks.

Also, explicitly use Python 3 since that's what default Ubuntu 16.04 seems
to want.
2016-09-17 11:30:01 -04:00
Andrew Gallant
5a0c873f61 Fixing, polishing and adding benchmarks. 2016-09-16 21:02:46 -04:00
Andrew Gallant
65fec147d6 rename 2016-09-16 18:27:34 -04:00
Andrew Gallant
7fbf2f014c Reorganize some files. 2016-09-16 18:22:35 -04:00
Andrew Gallant
d22a3ca3e5 Improve the "bad literal" error message.
Incidentally, this was done by using the Debug impl for `char` instead
of the Display impl. Cute.

Fixes #5.
2016-09-16 18:12:00 -04:00
Andrew Gallant
e9ec52b7f9 Update walkdir 2016-09-16 17:56:44 -04:00
Andrew Gallant
0d14c74e63 Some minor performance tweaks.
This includes moving basename-only globs into separate regexes. The hope
is that if the regex processes less input, it will be faster.
2016-09-16 16:13:28 -04:00
Andrew Gallant
1c5884b2f9 try again... 2016-09-16 07:12:06 -04:00
Andrew Gallant
8203a80ac7 fix tests 2016-09-16 06:58:10 -04:00
Andrew Gallant
0e46171e3b Rework glob sets.
We try to reduce the pressure on regexes and offload some of it to
Aho-Corasick or exact lookups.
2016-09-15 22:06:04 -04:00
Andrew Gallant
f5c85827ce Don't traverse directory stack if we don't need to. 2016-09-15 12:40:28 -04:00
Andrew Gallant
7cefc55238 Remove .agignore from ignore file list. 2016-09-15 12:40:08 -04:00
Andrew Gallant
92c918ebd9 --no-ignore implies --no-ignore-parent 2016-09-14 14:33:37 -04:00
Andrew Gallant
c24f8fd50f Replace crossbeam with deque.
deque appears faster.
2016-09-14 07:40:46 -04:00
Andrew Gallant
73272cf8a6 notice 2016-09-13 21:23:22 -04:00
Andrew Gallant
4212a8b9cb 0.1.1 2016-09-13 21:21:45 -04:00
Andrew Gallant
983c7fd6f9 We don't use thread_local any more, so remove it. 2016-09-13 21:21:36 -04:00
Andrew Gallant
7cd02e9b7e update Cargo.toml description 2016-09-13 21:16:29 -04:00
Andrew Gallant
5fdfae2f15 add readme 2016-09-13 21:15:10 -04:00
Andrew Gallant
7057ee91de update grep Cargo.toml 2016-09-13 21:13:33 -04:00
Andrew Gallant
fdca74148d Stream results when feasible.
For example, when only a single file (or stdin) is being searched, then we
should be able to print directly to the terminal instead of intermediate
buffers. (The buffers are only necessary for parallelism.)

Closes #4.
2016-09-13 21:11:46 -04:00
Andrew Gallant
f11d9fb922 Add a word benchmark.
Add ag to case insensitive benchmark.
2016-09-12 19:35:59 -04:00
Andrew Gallant
1115c23a4c fix typos 2016-09-11 19:50:16 -04:00
Andrew Gallant
8c5eaa40b2 teaser 2016-09-11 19:27:50 -04:00
Andrew Gallant
3c05954c86 initial set of benchmarks 2016-09-11 19:06:16 -04:00
Andrew Gallant
cf3a33cea7 commit Cargo.lock 2016-09-11 19:06:05 -04:00
Andrew Gallant
8aa2ba3eb1 update gitignore 2016-09-11 19:05:53 -04:00
Andrew Gallant
466cd70a8e More benchmarks for subtitle corpus. 2016-09-11 18:52:53 -04:00
Andrew Gallant
954fbeb1d8 Update regex. 2016-09-11 18:52:42 -04:00
Andrew Gallant
68fa50709e Don't skip the first arg.
Docopt will do it for us.
2016-09-11 13:33:25 -04:00
Andrew Gallant
ab91e4b874 Don't panic when an argument is invalid UTF-8.
Suggest a workaround.
2016-09-11 13:27:08 -04:00
Andrew Gallant
2b943eda47 Make file type filtering a lot faster.
We do this by avoiding using a RegexSet (*sigh*). In particular, file
type matching has much simpler semantics than gitignore files, so we don't
actually need to care which file type matched. Therefore, we can get away
with a single regex with a giant alternation.
2016-09-11 13:26:53 -04:00
Andrew Gallant
37544c092f We don't need regex-syntax directly in ripgrep. 2016-09-11 13:25:37 -04:00
Andrew Gallant
9bf7696ec8 Initial cut at a benchmark suite for CLI search tools. 2016-09-11 01:05:36 -04:00
Andrew Gallant
cb0f8fd2fa Bump default thread count to 8. 2016-09-11 00:42:39 -04:00
Andrew Gallant
fa8112ec34 Add alternative compile strategy (in a comment). 2016-09-11 00:42:30 -04:00
Andrew Gallant
cf21b4a97e Add doc. 2016-09-11 00:42:19 -04:00
Andrew Gallant
19615245cd Make line counting much faster. 2016-09-10 01:35:44 -04:00
Andrew Gallant
98a48b44bc Fix off-by-one bug in searcher. 2016-09-10 01:35:30 -04:00
Andrew Gallant
e3da726836 Rename search module to search_stream.
The name better reflects the difference between it and the search_buffer
module.
2016-09-10 00:08:42 -04:00
Andrew Gallant
5b36c86c15 Rejigger the atty detection stuff. 2016-09-10 00:05:20 -04:00
Andrew Gallant
76331e5fec Fix test that relied on non-deterministic order of results. 2016-09-09 23:24:01 -04:00
Andrew Gallant
1e678d7052 Fix files test. What a pain. 2016-09-09 23:19:46 -04:00
Andrew Gallant
dd986d7fe9 Add standard Linux CI (GNU libc). 2016-09-09 23:19:37 -04:00
Andrew Gallant
f83cd63b11 Add integration tests. 2016-09-09 22:58:30 -04:00
Andrew Gallant
9a4527d107 fix Rust version number in CI 2016-09-09 18:47:05 -04:00
Andrew Gallant
8f0d3d78ca clean up CI script 2016-09-09 18:10:20 -04:00
Andrew Gallant
3f7cd977bc expand Rust versions we test on. 2016-09-09 18:07:30 -04:00
Andrew Gallant
cc6b6dcf5b fix windows build 2016-09-09 08:53:10 -04:00
Andrew Gallant
48878bbb8f update project name 2016-09-08 21:47:49 -04:00
Andrew Gallant
0766617e07 Refactor how coloring is done.
All in the name of appeasing Windows.
2016-09-08 21:46:14 -04:00
Andrew Gallant
afd99c43d7 fix deploy 2016-09-08 16:35:48 -04:00
Andrew Gallant
96e87ab738 update distributable to include readme and license 2016-09-08 16:21:37 -04:00
Andrew Gallant
a744ec133d Rename xrep to ripgrep. 2016-09-08 16:15:44 -04:00
Andrew Gallant
0042dce949 Hack in Windows console coloring.
The code has suffered and needs refactoring/commenting. BUT... IT WORKS!
2016-09-07 21:54:28 -04:00
Andrew Gallant
ca058d7584 Add support for memory maps.
I though plain `read` had usurped them, but when searching a very small
number of files, mmaps can be around 20% faster on Linux. It'd be really
unfortunate to leave that on the table.

Mmap searching doesn't support contexts yet, but we probably don't really
care. And duplicating that logic doesn't sound fun. Without contexts, mmap
searching is delightfully simple.
2016-09-06 21:47:33 -04:00
Andrew Gallant
af3b56a623 Fix grep match iterator. 2016-09-06 21:45:41 -04:00
Andrew Gallant
5938bed339 Add support for printing column numbers. 2016-09-06 19:50:27 -04:00
Andrew Gallant
feff1849c8 Tweak colors. 2016-09-06 19:35:52 -04:00
Andrew Gallant
9948e0ca07 Only create the Grep searcher once. 2016-09-06 19:33:19 -04:00
Andrew Gallant
fd3e5069b6 Fix required literal handling and add debug prints.
In particular, if we had an inner literal and were doing a case insensitive
search, then the literals are dropped because we previously only allowed
a single inner literal to have an effect. Now we allow alternations of
inner literals, but still don't quite take full advantage.
2016-09-06 19:33:03 -04:00
Andrew Gallant
0891b4a3c0 update appveyor 2016-09-05 22:01:53 -04:00
Andrew Gallant
af48aaa647 another try 2016-09-05 21:57:57 -04:00
Andrew Gallant
ee7f300ae2 windows debug, take 1 2016-09-05 21:46:11 -04:00
62 changed files with 12373 additions and 1783 deletions

13
.gitignore vendored
View File

@@ -1,14 +1,5 @@
.*.swp
tags
target
*.lock
tmp
*.csv
*.fst
*-got
*.csv.idx
words
98m*
dict
test
months
/grep/Cargo.lock
/globset/Cargo.lock

View File

@@ -1,37 +1,43 @@
#language: rust
#rust:
# - stable
# - beta
# - nightly
#script:
# - cargo build --verbose
# - cargo doc
# - cargo test --verbose
# - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
# cargo bench --verbose;
# fi
language: rust
cache: cargo
env:
global:
- PROJECT_NAME=xrep
- PROJECT_NAME=ripgrep
matrix:
include:
# Nightly channel
- os: osx
rust: nightly
env: TARGET=i686-apple-darwin
- os: osx
rust: nightly
env: TARGET=x86_64-apple-darwin
# Nightly channel.
# (All *nix releases are done on the nightly channel to take advantage
# of the regex library's multiple pattern SIMD search.)
- os: linux
rust: nightly
env: TARGET=i686-unknown-linux-musl
- os: linux
rust: nightly
env: TARGET=x86_64-unknown-linux-musl
- os: osx
rust: nightly
env: TARGET=x86_64-apple-darwin
# Beta channel.
- os: linux
rust: beta
env: TARGET=x86_64-unknown-linux-musl
- os: linux
rust: beta
env: TARGET=x86_64-unknown-linux-gnu
- os: osx
rust: beta
env: TARGET=x86_64-apple-darwin
# Minimum Rust supported channel.
- os: linux
rust: 1.9.0
env: TARGET=x86_64-unknown-linux-musl
- os: linux
rust: 1.9.0
env: TARGET=x86_64-unknown-linux-gnu
- os: osx
rust: 1.9.0
env: TARGET=x86_64-apple-darwin
before_install:
- export PATH="$PATH:$HOME/.cargo/bin"

156
CHANGELOG.md Normal file
View File

@@ -0,0 +1,156 @@
0.2.3
=====
Bug fixes:
* [BUG #164](https://github.com/BurntSushi/ripgrep/issues/164):
Fixes a segfault on macos builds.
* [BUG #167](https://github.com/BurntSushi/ripgrep/issues/167):
Clarify documentation for --threads.
0.2.2
=====
Packaging updates:
* `ripgrep` is now in homebrew-core. `brew install ripgrep` will do the trick
on a Mac.
* `ripgrep` is now in the Archlinux community repository.
`pacman -S ripgrep` will do the trick on Archlinux.
* Support has been discontinued for i686-darwin.
* Glob matching has been moved out into its own crate:
[`globset`](https://crates.io/crates/globset).
Feature enhancements:
* Added or improved file type filtering for CMake, config, Jinja, Markdown,
Spark.
* [FEATURE #109](https://github.com/BurntSushi/ripgrep/issues/109):
Add a --max-depth flag for directory traversal.
* [FEATURE #124](https://github.com/BurntSushi/ripgrep/issues/124):
Add -s/--case-sensitive flag. Overrides --smart-case.
* [FEATURE #139](https://github.com/BurntSushi/ripgrep/pull/139):
The `ripgrep` repo is now a Homebrew tap. This is useful for installing
SIMD accelerated binaries, which aren't available in homebrew-core.
Bug fixes:
* [BUG #87](https://github.com/BurntSushi/ripgrep/issues/87),
[BUG #127](https://github.com/BurntSushi/ripgrep/issues/127),
[BUG #131](https://github.com/BurntSushi/ripgrep/issues/131):
Various issues related to glob matching.
* [BUG #116](https://github.com/BurntSushi/ripgrep/issues/116):
--quiet should stop search after first match.
* [BUG #121](https://github.com/BurntSushi/ripgrep/pull/121):
--color always should show colors, even when --vimgrep is used.
* [BUG #122](https://github.com/BurntSushi/ripgrep/pull/122):
Colorize file path at beginning of line.
* [BUG #134](https://github.com/BurntSushi/ripgrep/issues/134):
Processing a large ignore file (thousands of globs) was very slow.
* [BUG #137](https://github.com/BurntSushi/ripgrep/issues/137):
Always follow symlinks when given as an explicit argument.
* [BUG #147](https://github.com/BurntSushi/ripgrep/issues/147):
Clarify documentation for --replace.
0.2.1
=====
Feature enhancements:
* Added or improved file type filtering for Clojure and SystemVerilog.
* [FEATURE #89](https://github.com/BurntSushi/ripgrep/issues/89):
Add a --null flag that outputs a NUL byte after every file path.
Bug fixes:
* [BUG #98](https://github.com/BurntSushi/ripgrep/issues/98):
Fix a bug in single threaded mode when if opening a file failed, ripgrep
quit instead of continuing the search.
* [BUG #99](https://github.com/BurntSushi/ripgrep/issues/99):
Fix another bug in single threaded mode where empty lines were being printed
by mistake.
* [BUG #105](https://github.com/BurntSushi/ripgrep/issues/105):
Fix an off-by-one error with --column.
* [BUG #106](https://github.com/BurntSushi/ripgrep/issues/106):
Fix a bug where a whitespace only line in a gitignore file caused ripgrep
to panic (i.e., crash).
0.2.0
=====
Feature enhancements:
* Added or improved file type filtering for VB, R, F#, Swift, Nim, Javascript,
TypeScript
* [FEATURE #20](https://github.com/BurntSushi/ripgrep/issues/20):
Adds a --no-filename flag.
* [FEATURE #26](https://github.com/BurntSushi/ripgrep/issues/26):
Adds --files-with-matches flag. Like --count, but only prints file paths
and doesn't need to count every match.
* [FEATURE #40](https://github.com/BurntSushi/ripgrep/issues/40):
Switch from using `.rgignore` to `.ignore`. Note that `.rgignore` is
still supported, but deprecated.
* [FEATURE #68](https://github.com/BurntSushi/ripgrep/issues/68):
Add --no-ignore-vcs flag that ignores .gitignore but not .ignore.
* [FEATURE #70](https://github.com/BurntSushi/ripgrep/issues/70):
Add -S/--smart-case flag (but is disabled by default).
* [FEATURE #80](https://github.com/BurntSushi/ripgrep/issues/80):
Add support for `{foo,bar}` globs.
Many many bug fixes. Thanks every for reporting these and helping make
`ripgrep` better! (Note that I haven't captured every tracking issue here,
some were closed as duplicates.)
* [BUG #8](https://github.com/BurntSushi/ripgrep/issues/8):
Don't use an intermediate buffer when --threads=1. (Permits constant memory
usage.)
* [BUG #15](https://github.com/BurntSushi/ripgrep/issues/15):
Improves the documentation for --type-add.
* [BUG #16](https://github.com/BurntSushi/ripgrep/issues/16),
[BUG #49](https://github.com/BurntSushi/ripgrep/issues/49),
[BUG #50](https://github.com/BurntSushi/ripgrep/issues/50),
[BUG #65](https://github.com/BurntSushi/ripgrep/issues/65):
Some gitignore globs were being treated as anchored when they weren't.
* [BUG #18](https://github.com/BurntSushi/ripgrep/issues/18):
--vimgrep reported incorrect column number.
* [BUG #19](https://github.com/BurntSushi/ripgrep/issues/19):
ripgrep was hanging waiting on stdin in some Windows terminals. Note that
this introduced a new bug:
[#94](https://github.com/BurntSushi/ripgrep/issues/94).
* [BUG #21](https://github.com/BurntSushi/ripgrep/issues/21):
Removes leading `./` when printing file paths.
* [BUG #22](https://github.com/BurntSushi/ripgrep/issues/22):
Running `rg --help | echo` caused `rg` to panic.
* [BUG #24](https://github.com/BurntSushi/ripgrep/issues/22):
Clarify the central purpose of rg in its usage message.
* [BUG #25](https://github.com/BurntSushi/ripgrep/issues/25):
Anchored gitignore globs weren't applied in subdirectories correctly.
* [BUG #30](https://github.com/BurntSushi/ripgrep/issues/30):
Globs like `foo/**` should match contents of `foo`, but not `foo` itself.
* [BUG #35](https://github.com/BurntSushi/ripgrep/issues/35),
[BUG #81](https://github.com/BurntSushi/ripgrep/issues/81):
When automatically detecting stdin, only read if it's a file or a fifo.
i.e., ignore stdin in `rg foo < /dev/null`.
* [BUG #36](https://github.com/BurntSushi/ripgrep/issues/36):
Don't automatically pick memory maps on MacOS. Ever.
* [BUG #38](https://github.com/BurntSushi/ripgrep/issues/38):
Trailing whitespace in gitignore wasn't being ignored.
* [BUG #43](https://github.com/BurntSushi/ripgrep/issues/43):
--glob didn't work with directories.
* [BUG #46](https://github.com/BurntSushi/ripgrep/issues/46):
Use one fewer worker thread than what is provided on CLI.
* [BUG #47](https://github.com/BurntSushi/ripgrep/issues/47):
--help/--version now work even if other options are set.
* [BUG #55](https://github.com/BurntSushi/ripgrep/issues/55):
ripgrep was refusing to search /proc/cpuinfo. Fixed by disabling memory
maps for files with zero size.
* [BUG #64](https://github.com/BurntSushi/ripgrep/issues/64):
The first path given with --files set was ignored.
* [BUG #67](https://github.com/BurntSushi/ripgrep/issues/67):
Sometimes whitelist globs like `!/dir` weren't interpreted as anchored.
* [BUG #77](https://github.com/BurntSushi/ripgrep/issues/77):
When -q/--quiet flag was passed, ripgrep kept searching even after a match
was found.
* [BUG #90](https://github.com/BurntSushi/ripgrep/issues/90):
Permit whitelisting hidden files.
* [BUG #93](https://github.com/BurntSushi/ripgrep/issues/93):
ripgrep was extracting an erroneous inner literal from a repeated pattern.

267
Cargo.lock generated Normal file
View File

@@ -0,0 +1,267 @@
[root]
name = "ripgrep"
version = "0.2.2"
dependencies = [
"deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.1.0",
"grep 0.1.3",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "deque"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "docopt"
version = "0.6.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fnv"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fs2"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "globset"
version = "0.1.0"
dependencies = [
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "grep"
version = "0.1.3"
dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memmap"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fs2 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.1.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-serialize"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "simd"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "term"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread-id"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "walkdir"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
"checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
"checksum docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)" = "4a7ef30445607f6fc8720f0a0a2c7442284b629cf0d049286860fae23e71c4d9"
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
"checksum fs2 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bcd414e5a1a979b931bb92f41b7a54106d3f6d2e6c253e9ce943b7cd468251ef"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
"checksum libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "408014cace30ee0f767b1c4517980646a573ec61a57957aeeabcac8ac0a02e8d"
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
"checksum memmap 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f20f72ed93291a72e22e8b16bb18762183bb4943f0f483da5b8be1a9e8192752"
"checksum num_cpus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8890e6084723d57d0df8d2720b0d60c6ee67d6c93e7169630e4371e88765dcad"
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
"checksum regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)" = "64b03446c466d35b42f2a8b203c8e03ed8b91c0f17b56e1f84f7210a257aa665"
"checksum regex-syntax 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "48f0573bcee95a48da786f8823465b5f2a1fae288a55407aca991e5b3e0eae11"
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
"checksum simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5847c2d766ca7ce7227672850955802fabd779ba616aeabead4c2c3877023"
"checksum strsim 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "50c069df92e4b01425a8bf3576d5d417943a6a7272fbabaf5bd80b1aaa76442e"
"checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

View File

@@ -1,39 +1,44 @@
[package]
publish = false
name = "xrep"
version = "0.1.0" #:version
name = "ripgrep"
version = "0.2.3" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Line oriented search tool using Rust's regex library.
Line oriented search tool using Rust's regex library. Combines the raw
performance of grep with the usability of the silver searcher.
"""
documentation = "https://github.com/BurntSushi/xrep"
homepage = "https://github.com/BurntSushi/xrep"
repository = "https://github.com/BurntSushi/xrep"
documentation = "https://github.com/BurntSushi/ripgrep"
homepage = "https://github.com/BurntSushi/ripgrep"
repository = "https://github.com/BurntSushi/ripgrep"
readme = "README.md"
keywords = ["regex", "grep", "egrep", "search", "pattern"]
license = "Unlicense/MIT"
exclude = ["HomebrewFormula"]
[[bin]]
bench = false
path = "src/main.rs"
name = "xrep"
name = "rg"
[[test]]
name = "integration"
path = "tests/tests.rs"
[dependencies]
crossbeam = "0.2"
deque = "0.3"
docopt = "0.6"
env_logger = "0.3"
grep = { version = "0.1", path = "grep" }
globset = { version = "0.1.0", path = "globset" }
grep = { version = "0.1.3", path = "grep" }
lazy_static = "0.2"
libc = "0.2"
log = "0.3"
memchr = "0.1"
memmap = "0.2"
num_cpus = "1"
regex = "0.1.75"
regex-syntax = "0.3.5"
regex = "0.1.77"
rustc-serialize = "0.3"
term = "0.4"
thread_local = "0.2"
thread_local = "0.2.7"
walkdir = "0.1"
[target.'cfg(windows)'.dependencies]
@@ -43,9 +48,5 @@ winapi = "0.2"
[features]
simd-accel = ["regex/simd-accel"]
[dev-dependencies]
glob = "0.2"
[profile.release]
debug = true
panic = "abort"

1
HomebrewFormula Symbolic link
View File

@@ -0,0 +1 @@
pkg/brew

View File

@@ -1,14 +0,0 @@
all:
echo Nothing to do...
ctags:
ctags --options=ctags.rust --languages=Rust src/*.rs src/*/*.rs
docs:
cargo doc
in-dir ./target/doc fix-perms
rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/
push:
git push origin master
git push github master

274
README.md
View File

@@ -1,5 +1,269 @@
rep
---
A faster `grep`, written in Rust using the
[`regex`](https://github.com/rust-lang-nursery/regex)
crate.
ripgrep (rg)
------------
`ripgrep` is a command line search tool that combines the usability of The
Silver Searcher (an `ack` clone) with the raw speed of GNU grep. `ripgrep` has
first class support on Windows, Mac and Linux, with binary downloads available
for [every release](https://github.com/BurntSushi/ripgrep/releases).
[![Linux build status](https://api.travis-ci.org/BurntSushi/ripgrep.png)](https://travis-ci.org/BurntSushi/ripgrep)
[![Windows build status](https://ci.appveyor.com/api/projects/status/github/BurntSushi/ripgrep?svg=true)](https://ci.appveyor.com/project/BurntSushi/ripgrep)
[![](https://img.shields.io/crates/v/ripgrep.svg)](https://crates.io/crates/ripgrep)
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
### Screenshot of search results
[![A screenshot of a sample search with ripgrep](http://burntsushi.net/stuff/ripgrep1.png)](http://burntsushi.net/stuff/ripgrep1.png)
### Quick example comparing tools
This example searches the entire Linux kernel source tree (after running
`make defconfig && make -j8`) for `[A-Z]+_SUSPEND`, where all matches must be
words. Timings were collected on a system with an Intel i7-6900K 3.2 GHz.
Please remember that a single benchmark is never enough! See my
[blog post on `ripgrep`](http://blog.burntsushi.net/ripgrep/)
for a very detailed comparison with more benchmarks and analysis.
| Tool | Command | Line count | Time |
| ---- | ------- | ---------- | ---- |
| ripgrep | `rg -n -w '[A-Z]+_SUSPEND'` | 450 | **0.245s** |
| [The Silver Searcher](https://github.com/ggreer/the_silver_searcher) | `ag -w '[A-Z]+_SUSPEND'` | 450 | 0.753s |
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=C git grep -E -n -w '[A-Z]+_SUSPEND'` | 450 | 0.823s |
| [git grep (Unicode)](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=en_US.UTF-8 git grep -E -n -w '[A-Z]+_SUSPEND'` | 450 | 2.880s |
| [sift](https://github.com/svent/sift) | `sift --git -n -w '[A-Z]+_SUSPEND'` | 450 | 3.656s |
| [The Platinum Searcher](https://github.com/monochromegane/the_platinum_searcher) | `pt -w -e '[A-Z]+_SUSPEND'` | 450 | 12.369s |
| [ack](http://beyondgrep.com/) | `ack -w '[A-Z]+_SUSPEND'` | 1878 | 16.952s |
(Yes, `ack` [has](https://github.com/petdance/ack2/issues/445) a
[bug](https://github.com/petdance/ack2/issues/14).)
### Why should I use `ripgrep`?
* It can replace both The Silver Searcher and GNU grep because it is faster
than both. (N.B. It is not, strictly speaking, a "drop-in" replacement for
both, but the feature sets are far more similar than different.)
* Like The Silver Searcher, `ripgrep` defaults to recursive directory search
and won't search files ignored by your `.gitignore` files. It also ignores
hidden and binary files by default. `ripgrep` also implements full support
for `.gitignore`, where as there are many bugs related to that functionality
in The Silver Searcher.
* `ripgrep` can search specific types of files. For example, `rg -tpy foo`
limits your search to Python files and `rg -Tjs foo` excludes Javascript
files from your search. `ripgrep` can be taught about new file types with
custom matching rules.
* `ripgrep` supports many features found in `grep`, such as showing the context
of search results, searching multiple patterns, highlighting matches with
color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast while
supporting Unicode (which is always on).
In other words, use `ripgrep` if you like speed, sane defaults, fewer bugs and
Unicode.
### Is it really faster than everything else?
Yes. A large number of benchmarks with detailed analysis for each is
[available on my blog](http://blog.burntsushi.net/ripgrep/).
Summarizing, `ripgrep` is fast because:
* It is built on top of
[Rust's regex engine](https://github.com/rust-lang-nursery/regex).
Rust's regex engine uses finite automata, SIMD and aggressive literal
optimizations to make searching very fast.
* Rust's regex library maintains performance with full Unicode support by
building UTF-8 decoding directly into its deterministic finite automaton
engine.
* It supports searching with either memory maps or by searching incrementally
with an intermediate buffer. The former is better for single files and the
latter is better for large directories. `ripgrep` chooses the best searching
strategy for you automatically.
* Applies your ignore patterns in `.gitignore` files using a
[`RegexSet`](https://doc.rust-lang.org/regex/regex/struct.RegexSet.html).
That means a single file path can be matched against multiple glob patterns
simultaneously.
* Uses a Chase-Lev work-stealing queue for quickly distributing work to
multiple threads.
### Installation
The binary name for `ripgrep` is `rg`.
[Binaries for `ripgrep` are available for Windows, Mac and
Linux.](https://github.com/BurntSushi/ripgrep/releases) Linux binaries are
static executables. Windows binaries are available either as built with MinGW
(GNU) or with Microsoft Visual C++ (MSVC). When possible, prefer MSVC over GNU,
but you'll need to have the
[Microsoft VC++ 2015 redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=48145)
installed.
If you're a **Mac OS X Homebrew** user, then you can install ripgrep either
from homebrew-core, (compiled with rust stable, no SIMD):
```
$ brew install ripgrep
```
or you can install a binary compiled with rust nightly (including SIMD and all
optimizations) by utilizing a custom tap:
```
$ brew tap burntsushi/ripgrep https://github.com/BurntSushi/ripgrep.git
$ brew install burntsushi/ripgrep/ripgrep-bin
```
If you're an **Arch Linux** user, then you can install `ripgrep` from the official repos:
```
$ pacman -S ripgrep
```
If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`:
```
$ cargo install ripgrep
```
`ripgrep` isn't currently in any other package repositories.
[I'd like to change that](https://github.com/BurntSushi/ripgrep/issues/10).
### Whirlwind tour
The command line usage of `ripgrep` doesn't differ much from other tools that
perform a similar function, so you probably already know how to use `ripgrep`.
The full details can be found in `rg --help`, but let's go on a whirlwind tour.
`ripgrep` detects when its printing to a terminal, and will automatically
colorize your output and show line numbers, just like The Silver Searcher.
Coloring works on Windows too! Colors can be controlled more granularly with
the `--color` flag.
One last thing before we get started: `ripgrep` assumes UTF-8 *everywhere*. It
can still search files that are invalid UTF-8 (like, say, latin-1), but it will
simply not work on UTF-16 encoded files or other more exotic encodings.
[Support for other encodings may
happen.](https://github.com/BurntSushi/ripgrep/issues/1)
To recursively search the current directory, while respecting all `.gitignore`
files, ignore hidden files and directories and skip binary files:
```
$ rg foobar
```
The above command also respects all `.ignore` files, including in parent
directories. `.ignore` files can be used when `.gitignore` files are
insufficient. In all cases, `.ignore` patterns take precedence over
`.gitignore`.
To ignore all ignore files, use `-u`. To additionally search hidden files
and directories, use `-uu`. To additionally search binary files, use `-uuu`.
(In other words, "search everything, dammit!") In particular, `rg -uuu` is
similar to `grep -a -r`.
```
$ rg -uu foobar # similar to `grep -r`
$ rg -uuu foobar # similar to `grep -a -r`
```
(Tip: If your ignore files aren't being adhered to like you expect, run your
search with the `--debug` flag.)
Make the search case insensitive with `-i`, invert the search with `-v` or
show the 2 lines before and after every search result with `-C2`.
Force all matches to be surrounded by word boundaries with `-w`.
Search and replace (find first and last names and swap them):
```
$ rg '([A-Z][a-z]+)\s+([A-Z][a-z]+)' --replace '$2, $1'
```
Named groups are supported:
```
$ rg '(?P<first>[A-Z][a-z]+)\s+(?P<last>[A-Z][a-z]+)' --replace '$last, $first'
```
Up the ante with full Unicode support, by matching any uppercase Unicode letter
followed by any sequence of lowercase Unicode letters (good luck doing this
with other search tools!):
```
$ rg '(\p{Lu}\p{Ll}+)\s+(\p{Lu}\p{Ll}+)' --replace '$2, $1'
```
Search only files matching a particular glob:
```
$ rg foo -g 'README.*'
```
<!--*-->
Or exclude files matching a particular glob:
```
$ rg foo -g '!*.min.js'
```
Search only HTML and CSS files:
```
$ rg -thtml -tcss foobar
```
Search everything except for Javascript files:
```
$ rg -Tjs foobar
```
To see a list of types supported, run `rg --type-list`. To add a new type, use
`--type-add`, which must be accompanied by a pattern for searching (`rg` won't
persist your type settings):
```
$ rg --type-add 'foo:*.{foo,foobar}' -tfoo bar
```
The type `foo` will now match any file ending with the `.foo` or `.foobar`
extensions.
### Regex syntax
The syntax supported is
[documented as part of Rust's regex library](https://doc.rust-lang.org/regex/regex/index.html#syntax).
### Building
`ripgrep` is written in Rust, so you'll need to grab a
[Rust installation](https://www.rust-lang.org/) in order to compile it.
`ripgrep` compiles with Rust 1.9 (stable) or newer. Building is easy:
```
$ git clone https://github.com/BurntSushi/ripgrep
$ cd ripgrep
$ cargo build --release
$ ./target/release/rg --version
0.1.3
```
If you have a Rust nightly compiler, then you can enable optional SIMD
acceleration like so:
```
RUSTFLAGS="-C target-cpu=native" cargo build --release --features simd-accel
```
### Running tests
`ripgrep` is relatively well tested, including both unit tests and integration
tests. To run the full test suite, use:
```
$ cargo test
```
from the repository root.

View File

@@ -1,28 +1,23 @@
environment:
global:
PROJECT_NAME: xrep
PROJECT_NAME: ripgrep
matrix:
# Nightly channel
- TARGET: i686-pc-windows-gnu
CHANNEL: nightly
CHANNEL: stable
- TARGET: i686-pc-windows-msvc
CHANNEL: nightly
CHANNEL: stable
- TARGET: x86_64-pc-windows-gnu
CHANNEL: nightly
CHANNEL: stable
- TARGET: x86_64-pc-windows-msvc
CHANNEL: nightly
CHANNEL: stable
# Install Rust and Cargo
# (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml)
install:
- ps: Start-FileDownload "https://static.rust-lang.org/dist/channel-rust-stable"
- ps: $env:RUST_VERSION = Get-Content channel-rust-stable | select -first 1 | %{$_.split('-')[1]}
- if NOT "%CHANNEL%" == "stable" set RUST_VERSION=%CHANNEL%
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:RUST_VERSION}-${env:TARGET}.exe"
- rust-%RUST_VERSION%-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- if "%TARGET%" == "i686-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw32\bin
- if "%TARGET%" == "x86_64-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw64\bin
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host %TARGET%
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
- if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin
- rustc -V
- cargo -V
@@ -32,23 +27,23 @@ build: false
# Equivalent to Travis' `script` phase
# TODO modify this phase as you see fit
test_script:
- cargo build --verbose
- cargo test
- cargo test --verbose
- cargo test --verbose --manifest-path grep/Cargo.toml
- cargo test --verbose --manifest-path globset/Cargo.toml
before_deploy:
# Generate artifacts for release
- SET RUSTFLAGS="-C target-feature=+ssse3"
- cargo build --release --features simd-accel
# TODO(burntsushi): How can we enable SSSE3 on Windows?
- cargo build --release
- mkdir staging
# TODO update this part to copy the artifacts that make sense for your project
- copy target\release\xrep.exe staging
- copy target\release\rg.exe staging
- cd staging
# release zipfile will look like 'rust-everywhere-v1.2.3-x86_64-pc-windows-msvc'
- 7z a ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip *
- appveyor PushArtifact ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip
deploy:
description: 'Windows release'
description: 'Automatically deployed release'
# All the zipped artifacts will be deployed
artifact: /.*\.zip/
auth_token:
@@ -59,7 +54,7 @@ deploy:
# channel to use to produce the release artifacts
# NOTE make sure you only release *once* per target
# TODO you may want to pick a different channel
CHANNEL: nightly
CHANNEL: stable
appveyor_repo_tag: true
branches:

1305
benchsuite/benchsuite Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
Ubuntu 16.04 HVM AMI
c3.2xlarge, Xeon E5-2680, 2.8 GHz, 8 CPUs, 16 GB memory, 80 GB SSD
# Generic system setup
mkfs.ext4 /dev/xvdb
sudo mount /dev/xvdb /mnt
sudo chown ubuntu /mnt
sudo apt-get update
sudo apt-get install \ # for building Linux kernel
make gcc bc
sudo apt-get install \ # for the silver searcher
automake pkg-config zlib1g-dev liblzma-dev libpcre3 libpcre3-dev
sudo apt-get install \ # for Universal Code Grep
libtool libpcre2-8-0 libpcre2-dev
sudo apt-get install \ # for sift and the platinum searcher
go
# Get benchmark corpora
cd /mnt
mkdir /mnt/bench
git clone git://github.com/BurntSushi/ripgrep
cd ripgrep/benchsuite
./benchsuite --dir /mnt/bench/ --download all # takes around 15 minutes
# Install search tools
mkdir /mnt/bin/
## ripgrep
cd /mnt
mkdir ripgrep-bin
cd ripgrep-bin
curl -LO 'https://github.com/BurntSushi/ripgrep/releases/download/0.1.2/ripgrep-0.1.2-x86_64-unknown-linux-musl.tar.gz'
cp ripgrep-0.1.2-x86_64-unknown-linux-musl/rg /mnt/bin/
## The Silver Searcher
cd /mnt
git clone git://github.com/ggreer/the_silver_searcher
cd the_silver_searcher
git checkout cda635
./build.sh
cp ag /mnt/bin/
## Universal Code Grep
cd /mnt
git clone git://github.com/gvansickle/ucg
cd ucg
git checkout 487bfb
autoreconf -i
./configure
make
cp ucg /mnt/bin/
## The Platinum Searcher
export GOPATH=/mnt/go
go get github.com/monochromegane/the_platinum_searcher
cd /mnt/go/src/github.com/monochromegane/the_platinum_searcher
git checkout 509368
go install github.com/monochromegane/the_platinum_searcher/cmd/...
cp /mnt/go/bin/pt /mnt/bin/
## Sift
export GOPATH=/mnt/go
go get github.com/svent/sift
cd /mnt/go/src/github.com/svent/sift
git checkout 2d175c
go install
cp /mnt/go/bin/sift /mnt/bin/
## 'git grep' and GNU grep
They are part of the standard Ubuntu install, and are pretty recent (as of
September 2016).
$ git --version
git version 2.7.4
$ grep --version
grep (GNU grep) 2.25
# Running benchmarks
export PATH="/mnt/bin:$PATH"
cd /mnt/ripgrep/benchsuite
./benchsuite --dir /mnt/bench/ --raw /mnt/bench/raw.csv \
| tee /mnt/bench/summary
# The above took around 30 minutes to run to completion.

View File

@@ -0,0 +1,457 @@
benchmark,warmup_iter,iter,name,command,duration,lines,env
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.30042552947998047,68,
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.3699159622192383,68,
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.2950403690338135,68,
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.7572166919708252,68,
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.7568728923797607,68,
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.7468714714050293,68,
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5062770843505859,68,LC_ALL=C
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.49932026863098145,68,LC_ALL=C
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5008277893066406,68,LC_ALL=C
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.19775605201721191,68,
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.19699668884277344,68,
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.19636178016662598,68,
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.21344256401062012,68,
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.21743154525756836,68,
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22065043449401855,68,
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.31632304191589355,160,
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.3168807029724121,160,
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.4834277629852295,160,
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.9558978080749512,160,
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.9736671447753906,160,
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.9648356437683105,160,
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,2.0229439735412598,160,LC_ALL=C
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,2.0214922428131104,160,LC_ALL=C
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,2.022616147994995,160,LC_ALL=C
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22146987915039062,160,
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22275280952453613,160,
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22226715087890625,160,
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5290391445159912,160,
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5196049213409424,160,
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5219125747680664,160,
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.2871882915496826,16,
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.38920140266418457,16,
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.3668382167816162,16,
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,1.6073203086853027,16,
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,1.6012177467346191,16,
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,1.5818352699279785,16,
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,1.592775583267212,16,
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,1.5901448726654053,16,
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,1.586061716079712,16,
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.45094990730285645,16,
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.47065186500549316,16,
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.4422800540924072,16,
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.6293809413909912,16,
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.6314799785614014,16,
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.6289358139038086,16,
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.347550630569458,16,LC_ALL=C
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.345928430557251,16,LC_ALL=C
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.33939385414123535,16,LC_ALL=C
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.20830345153808594,16,
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.34220385551452637,16,
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.2077772617340088,16,
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.21996808052062988,16,
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.22822093963623047,16,
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.21923017501831055,16,
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.2988588809967041,370,
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.5339267253875732,370,
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.43750762939453125,370,
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,1.603757381439209,370,
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,1.618077278137207,370,
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,1.6234121322631836,370,
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,1.621368646621704,370,
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,1.5698626041412354,370,
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,1.6105949878692627,370,
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.8005843162536621,370,
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.8044955730438232,370,
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.806922197341919,370,
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.34161829948425293,370,LC_ALL=C
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.3455958366394043,370,LC_ALL=C
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.3493361473083496,370,LC_ALL=C
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.2149522304534912,370,
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.21602368354797363,370,
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.27021098136901855,370,
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.22747421264648438,370,
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.22050881385803223,370,
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.21217584609985352,370,
linux_literal_default,1,3,rg,rg PM_RESUME,0.27482175827026367,16,
linux_literal_default,1,3,rg,rg PM_RESUME,0.2796294689178467,16,
linux_literal_default,1,3,rg,rg PM_RESUME,0.27638936042785645,16,
linux_literal_default,1,3,ag,ag PM_RESUME,1.598384141921997,16,
linux_literal_default,1,3,ag,ag PM_RESUME,1.5849597454071045,16,
linux_literal_default,1,3,ag,ag PM_RESUME,1.6000149250030518,16,
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.2263963222503662,16,
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.21367835998535156,16,
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.21764111518859863,16,
linux_literal_default,1,3,pt,pt PM_RESUME,0.42263340950012207,16,
linux_literal_default,1,3,pt,pt PM_RESUME,0.467041015625,16,
linux_literal_default,1,3,pt,pt PM_RESUME,0.42820048332214355,16,
linux_literal_default,1,3,sift,sift PM_RESUME,0.33421826362609863,16,
linux_literal_default,1,3,sift,sift PM_RESUME,0.35932135581970215,16,
linux_literal_default,1,3,sift,sift PM_RESUME,0.3372631072998047,16,
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.348984956741333,16,LC_ALL=en_US.UTF-8
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.34420299530029297,16,LC_ALL=en_US.UTF-8
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.33880615234375,16,LC_ALL=en_US.UTF-8
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.5833027362823486,490,
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.5783836841583252,490,
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.5806806087493896,490,
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4163496494293213,490,
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4040029048919678,490,
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.40265560150146484,490,
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.3176910877227783,766,
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.3504347801208496,766,
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.317542552947998,766,
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},25.821982383728027,491,
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},25.82067561149597,491,
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},25.626302242279053,491,
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},26.349210023880005,490,LC_ALL=en_US.UTF-8
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},26.34226369857788,490,LC_ALL=en_US.UTF-8
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},26.340656995773315,490,LC_ALL=en_US.UTF-8
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},4.14680290222168,490,LC_ALL=C
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},4.153340578079224,490,LC_ALL=C
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},4.154819011688232,490,LC_ALL=C
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.49768829345703125,419,
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.5121400356292725,419,
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.49718427658081055,419,
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.38550543785095215,419,
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.32651591300964355,419,
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3246915340423584,419,
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.128183126449585,416,
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.1255216598510742,416,
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.1268525123596191,416,
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.36306214332580566,1652,
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.45077037811279297,1652,
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.3804624080657959,1652,
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,1.8995850086212158,1652,
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,1.8897662162780762,1652,
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,1.878380537033081,1652,
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,10.48949646949768,1652,
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,10.289165735244751,1652,
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,10.000468254089355,1652,
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,1.1080453395843506,1652,LC_ALL=C
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,1.10821533203125,1652,LC_ALL=C
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,1.105595588684082,1652,LC_ALL=C
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.2073357105255127,1630,
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.20552492141723633,1630,
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.2061319351196289,1630,
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.3013310432434082,1630,
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.3005218505859375,1630,
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.29984378814697266,1630,
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.4162716865539551,23,
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.47885966300964355,23,
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.5135962963104248,23,
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},7.570494651794434,23,
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},7.790151596069336,23,
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},7.783358812332153,23,
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.4370443820953369,103,
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.40680766105651855,103,
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.4011569023132324,103,
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.002422809600830078,,
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.002414226531982422,,
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.002293109893798828,,
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.44771265983581543,186,
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.3006107807159424,186,
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.3026111125946045,186,
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.43827080726623535,174,
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.2931697368621826,174,
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.33072638511657715,174,
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,1.7645132541656494,174,
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,1.7730333805084229,174,
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,1.773383378982544,174,
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh,10.872124671936035,174,
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh,11.147738456726074,174,
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh,11.029243469238281,174,
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,13.047154664993286,186,LC_ALL=en_US.UTF-8
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,13.025037288665771,186,LC_ALL=en_US.UTF-8
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,13.081012487411499,186,LC_ALL=en_US.UTF-8
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,2.98722767829895,174,LC_ALL=C
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,2.987990379333496,174,LC_ALL=C
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,2.988698959350586,174,LC_ALL=C
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.21961355209350586,180,
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.2884254455566406,180,
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.21905040740966797,180,
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.23966765403747559,168,
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.21801042556762695,168,
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.21909880638122559,168,
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.2259504795074463,168,
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.22269177436828613,168,
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.2259974479675293,168,
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.34968090057373047,6,
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.28850769996643066,6,
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.34809160232543945,6,
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,1.6134660243988037,6,
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,1.59847092628479,6,
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,1.581369161605835,6,
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,7.644887208938599,6,
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,7.8782219886779785,6,
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,7.754150152206421,6,
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.34302353858947754,6,LC_ALL=C
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.33672142028808594,6,LC_ALL=C
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.35193610191345215,6,LC_ALL=C
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.33329272270202637,6,
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.25751829147338867,6,
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.21761608123779297,6,
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.22014284133911133,6,
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.22314929962158203,6,
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.2202434539794922,6,
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.622809886932373,848,
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6181182861328125,848,
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6205663681030273,848,
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.7565691471099854,848,
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.7561769485473633,848,
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.7559969425201416,848,
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.4493463039398193,848,
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.44877028465271,848,
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.4433801174163818,848,
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4114174842834473,848,LC_ALL=C
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.411625862121582,848,LC_ALL=C
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.408623456954956,848,LC_ALL=C
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2900726795196533,848,
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2905848026275635,848,
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2903940677642822,848,
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.9546515941619873,848,LC_ALL=C
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.955279588699341,848,LC_ALL=C
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.954089403152466,848,LC_ALL=C
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.169135332107544,862,
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.174601078033447,862,
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.1684675216674805,862,
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4171736240386963,862,
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4158167839050293,862,
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4186513423919678,862,
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.531639575958252,862,LC_ALL=C
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.526550054550171,862,LC_ALL=C
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.528509140014648,862,LC_ALL=C
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.722398281097412,862,
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7225935459136963,862,
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7222185134887695,862,
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.12151837348938,862,LC_ALL=en_US.UTF-8
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.119963884353638,862,LC_ALL=en_US.UTF-8
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.121079683303833,862,LC_ALL=en_US.UTF-8
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2684764862060547,629,
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.26811957359313965,629,
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2684173583984375,629,
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.435128688812256,629,
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4362881183624268,629,
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4399220943450928,629,
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.32662391662597656,629,
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.3277275562286377,629,
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.32798290252685547,629,
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.520500659942627,629,LC_ALL=C
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5191032886505127,629,LC_ALL=C
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5171597003936768,629,LC_ALL=C
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.595801830291748,629,
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5954360961914062,629,
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5945618152618408,629,
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7291676998138428,629,
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.730966329574585,629,
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.728854179382324,629,
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.775996208190918,629,
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7760195732116699,629,
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7763564586639404,629,
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.433366060256958,629,
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4338581562042236,629,
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.435924768447876,629,
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7586827278137207,629,
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7590317726135254,629,
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.754432201385498,629,
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9726488590240479,629,LC_ALL=C
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9699857234954834,629,LC_ALL=C
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9714112281799316,629,LC_ALL=C
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.36658453941345215,642,
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.3654778003692627,642,
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.36565113067626953,642,
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.0890116691589355,642,LC_ALL=en_US.UTF-8
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.08124852180481,642,LC_ALL=en_US.UTF-8
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.0796849727630615,642,LC_ALL=en_US.UTF-8
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6151647567749023,642,LC_ALL=C
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6141552925109863,642,LC_ALL=C
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6132988929748535,642,LC_ALL=C
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6962459087371826,642,
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6945579051971436,642,
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.693866491317749,642,
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.771639823913574,642,
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.772296190261841,642,
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7712018489837646,642,
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.8068230152130127,642,
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.80411696434021,642,
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.8038516044616699,642,
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5951778888702393,629,
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5971941947937012,629,
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5952184200286865,629,
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7292284965515137,629,
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.728681802749634,629,
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7315311431884766,629,
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.784024715423584,629,
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.780540943145752,629,
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7772648334503174,629,
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9744353294372559,629,LC_ALL=C
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9781327247619629,629,LC_ALL=C
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9798097610473633,629,LC_ALL=C
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5965189933776855,629,
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5960156917572021,629,
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5975723266601562,629,
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9818971157073975,629,LC_ALL=en_US.UTF-8
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9785251617431641,629,LC_ALL=en_US.UTF-8
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.977081298828125,629,LC_ALL=en_US.UTF-8
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7750890254974365,13,
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.774017333984375,13,
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.783200740814209,13,
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.5396409034729004,13,
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.5404820442199707,13,
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.5400590896606445,13,
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,10.072888612747192,48,
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,10.075153350830078,48,
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,10.0713791847229,48,
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,7.734791278839111,13,
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,7.7345263957977295,13,
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,7.73199462890625,13,
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.411367416381836,13,LC_ALL=C
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.41072940826416,13,LC_ALL=C
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.414730072021484,13,LC_ALL=C
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6052529811859131,317,
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6049232482910156,317,
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6045565605163574,317,
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.2849924564361572,317,LC_ALL=en_US.UTF-8
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.2837722301483154,317,LC_ALL=en_US.UTF-8
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.2847650051116943,317,LC_ALL=en_US.UTF-8
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6005992889404297,317,
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.600543737411499,317,
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6009273529052734,317,
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,11.664374113082886,323,
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,11.674306869506836,323,
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,11.657484769821167,323,
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.650290012359619,317,
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.651855707168579,317,
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.649921417236328,317,
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.2745037078857422,317,LC_ALL=C
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.275665521621704,317,LC_ALL=C
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.273988962173462,317,LC_ALL=C
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.9031155109405518,691,
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.9021081924438477,691,
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.9028818607330322,691,
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.8895978927612305,691,
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.891357660293579,691,
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.892467975616455,691,
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7517757415771484,691,
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7550888061523438,691,
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7555651664733887,691,
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.51417875289917,691,LC_ALL=C
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.512972116470337,691,LC_ALL=C
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.507266521453857,691,LC_ALL=C
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.300950288772583,691,
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.2987852096557617,691,
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3024635314941406,691,
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,7.983739137649536,691,LC_ALL=C
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,7.988446950912476,691,LC_ALL=C
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,7.979671478271484,691,LC_ALL=C
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.889382362365723,691,
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.902577877044678,691,
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.890571355819702,691,
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7548162937164307,691,
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.747791051864624,691,
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7396674156188965,691,
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.58053183555603,691,LC_ALL=C
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.594751596450806,691,LC_ALL=C
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.561670541763306,691,LC_ALL=C
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.833597183227539,735,
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.831137180328369,735,
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.830361843109131,735,
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.723876953125,735,LC_ALL=en_US.UTF-8
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.723239183425903,735,LC_ALL=en_US.UTF-8
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.722000360488892,735,LC_ALL=en_US.UTF-8
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.3252851963043213,583,
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.3270294666290283,583,
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.32680773735046387,583,
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.932488679885864,583,
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.91330337524414,583,
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.911381006240845,583,
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,16.438587427139282,583,
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,16.412389755249023,583,
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,16.412444353103638,583,
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7865939140319824,583,LC_ALL=C
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7889957427978516,583,LC_ALL=C
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7923679351806641,583,LC_ALL=C
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9255633354187012,583,
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9285938739776611,583,
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9274048805236816,583,
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.4811036586761475,583,
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.4785168170928955,583,
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.484618186950684,583,
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7743628025054932,583,
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7731456756591797,583,
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7749128341674805,583,
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.931540250778198,583,
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.935162782669067,583,
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.949711561203003,583,
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,17.183809995651245,583,
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,17.19060492515564,583,
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,17.17626404762268,583,
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3023960590362549,583,LC_ALL=C
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.2992589473724365,583,LC_ALL=C
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.299330711364746,583,LC_ALL=C
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.1320264339447021,604,
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.1323668956756592,604,
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.1354515552520752,604,
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.194744348526001,604,LC_ALL=en_US.UTF-8
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.190656423568726,604,LC_ALL=en_US.UTF-8
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.18506383895874,604,LC_ALL=en_US.UTF-8
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7826528549194336,583,LC_ALL=C
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7846219539642334,583,LC_ALL=C
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7846999168395996,583,LC_ALL=C
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.734788179397583,604,
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7333040237426758,604,
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.731860637664795,604,
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7297205924987793,,
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7314808368682861,,
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7289514541625977,,
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7773914337158203,583,
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.774536371231079,583,
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7740859985351562,583,
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.3252553939819336,,
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.32543301582336426,,
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.32512736320495605,,
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7519562244415283,,
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.752692699432373,,
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7524521350860596,,
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7868170738220215,583,
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7786612510681152,583,
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.776214838027954,583,
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.303652286529541,583,LC_ALL=C
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3012151718139648,583,LC_ALL=C
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.307457685470581,583,LC_ALL=C
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9280951023101807,579,
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9285900592803955,579,
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9288535118103027,579,
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3026466369628906,579,LC_ALL=en_US.UTF-8
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3016819953918457,579,LC_ALL=en_US.UTF-8
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3006587028503418,579,LC_ALL=en_US.UTF-8
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.895586729049683,41,
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.914353132247925,41,
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.902980327606201,41,
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,3.972637891769409,,
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,3.9723849296569824,,
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,3.9723057746887207,,
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.3936586380004883,,
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.3987748622894287,,
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.393911361694336,,
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.8932065963745117,,
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.8977222442626953,,
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.893040895462036,,
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.4844722747802734,,LC_ALL=C
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.485093116760254,,LC_ALL=C
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.482459306716919,,LC_ALL=C
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9564735889434814,278,
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9561436176300049,278,
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9558789730072021,278,
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.6620113849639893,278,LC_ALL=en_US.UTF-8
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.6624438762664795,278,LC_ALL=en_US.UTF-8
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.6610260009765625,278,LC_ALL=en_US.UTF-8
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.4094629287719727,,
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.409822702407837,,
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.4094691276550293,,
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.866976261138916,,
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.8666067123413086,,
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.865297317504883,,
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.602109670639038,,LC_ALL=C
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.598329782485962,,LC_ALL=C
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.5975282192230225,,LC_ALL=C
1 benchmark warmup_iter iter name command duration lines env
2 linux_alternates 1 3 rg (ignore) rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.30042552947998047 68
3 linux_alternates 1 3 rg (ignore) rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.3699159622192383 68
4 linux_alternates 1 3 rg (ignore) rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.2950403690338135 68
5 linux_alternates 1 3 ag (ignore) ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 1.7572166919708252 68
6 linux_alternates 1 3 ag (ignore) ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 1.7568728923797607 68
7 linux_alternates 1 3 ag (ignore) ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 1.7468714714050293 68
8 linux_alternates 1 3 git grep (ignore) git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.5062770843505859 68 LC_ALL=C
9 linux_alternates 1 3 git grep (ignore) git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.49932026863098145 68 LC_ALL=C
10 linux_alternates 1 3 git grep (ignore) git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.5008277893066406 68 LC_ALL=C
11 linux_alternates 1 3 rg (whitelist) rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.19775605201721191 68
12 linux_alternates 1 3 rg (whitelist) rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.19699668884277344 68
13 linux_alternates 1 3 rg (whitelist) rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.19636178016662598 68
14 linux_alternates 1 3 ucg (whitelist) ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.21344256401062012 68
15 linux_alternates 1 3 ucg (whitelist) ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.21743154525756836 68
16 linux_alternates 1 3 ucg (whitelist) ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.22065043449401855 68
17 linux_alternates_casei 1 3 rg (ignore) rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.31632304191589355 160
18 linux_alternates_casei 1 3 rg (ignore) rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.3168807029724121 160
19 linux_alternates_casei 1 3 rg (ignore) rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.4834277629852295 160
20 linux_alternates_casei 1 3 ag (ignore) ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 1.9558978080749512 160
21 linux_alternates_casei 1 3 ag (ignore) ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 1.9736671447753906 160
22 linux_alternates_casei 1 3 ag (ignore) ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 1.9648356437683105 160
23 linux_alternates_casei 1 3 git grep (ignore) git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 2.0229439735412598 160 LC_ALL=C
24 linux_alternates_casei 1 3 git grep (ignore) git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 2.0214922428131104 160 LC_ALL=C
25 linux_alternates_casei 1 3 git grep (ignore) git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 2.022616147994995 160 LC_ALL=C
26 linux_alternates_casei 1 3 rg (whitelist) rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.22146987915039062 160
27 linux_alternates_casei 1 3 rg (whitelist) rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.22275280952453613 160
28 linux_alternates_casei 1 3 rg (whitelist) rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.22226715087890625 160
29 linux_alternates_casei 1 3 ucg (whitelist) ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.5290391445159912 160
30 linux_alternates_casei 1 3 ucg (whitelist) ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.5196049213409424 160
31 linux_alternates_casei 1 3 ucg (whitelist) ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.5219125747680664 160
32 linux_literal 1 3 rg (ignore) rg -n PM_RESUME 0.2871882915496826 16
33 linux_literal 1 3 rg (ignore) rg -n PM_RESUME 0.38920140266418457 16
34 linux_literal 1 3 rg (ignore) rg -n PM_RESUME 0.3668382167816162 16
35 linux_literal 1 3 rg (ignore) (mmap) rg -n --mmap PM_RESUME 1.6073203086853027 16
36 linux_literal 1 3 rg (ignore) (mmap) rg -n --mmap PM_RESUME 1.6012177467346191 16
37 linux_literal 1 3 rg (ignore) (mmap) rg -n --mmap PM_RESUME 1.5818352699279785 16
38 linux_literal 1 3 ag (ignore) (mmap) ag -s PM_RESUME 1.592775583267212 16
39 linux_literal 1 3 ag (ignore) (mmap) ag -s PM_RESUME 1.5901448726654053 16
40 linux_literal 1 3 ag (ignore) (mmap) ag -s PM_RESUME 1.586061716079712 16
41 linux_literal 1 3 pt (ignore) pt PM_RESUME 0.45094990730285645 16
42 linux_literal 1 3 pt (ignore) pt PM_RESUME 0.47065186500549316 16
43 linux_literal 1 3 pt (ignore) pt PM_RESUME 0.4422800540924072 16
44 linux_literal 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME 0.6293809413909912 16
45 linux_literal 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME 0.6314799785614014 16
46 linux_literal 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME 0.6289358139038086 16
47 linux_literal 1 3 git grep (ignore) git grep -I -n PM_RESUME 0.347550630569458 16 LC_ALL=C
48 linux_literal 1 3 git grep (ignore) git grep -I -n PM_RESUME 0.345928430557251 16 LC_ALL=C
49 linux_literal 1 3 git grep (ignore) git grep -I -n PM_RESUME 0.33939385414123535 16 LC_ALL=C
50 linux_literal 1 3 rg (whitelist) rg -n --no-ignore -tall PM_RESUME 0.20830345153808594 16
51 linux_literal 1 3 rg (whitelist) rg -n --no-ignore -tall PM_RESUME 0.34220385551452637 16
52 linux_literal 1 3 rg (whitelist) rg -n --no-ignore -tall PM_RESUME 0.2077772617340088 16
53 linux_literal 1 3 ucg (whitelist) ucg --nosmart-case PM_RESUME 0.21996808052062988 16
54 linux_literal 1 3 ucg (whitelist) ucg --nosmart-case PM_RESUME 0.22822093963623047 16
55 linux_literal 1 3 ucg (whitelist) ucg --nosmart-case PM_RESUME 0.21923017501831055 16
56 linux_literal_casei 1 3 rg (ignore) rg -n -i PM_RESUME 0.2988588809967041 370
57 linux_literal_casei 1 3 rg (ignore) rg -n -i PM_RESUME 0.5339267253875732 370
58 linux_literal_casei 1 3 rg (ignore) rg -n -i PM_RESUME 0.43750762939453125 370
59 linux_literal_casei 1 3 rg (ignore) (mmap) rg -n -i --mmap PM_RESUME 1.603757381439209 370
60 linux_literal_casei 1 3 rg (ignore) (mmap) rg -n -i --mmap PM_RESUME 1.618077278137207 370
61 linux_literal_casei 1 3 rg (ignore) (mmap) rg -n -i --mmap PM_RESUME 1.6234121322631836 370
62 linux_literal_casei 1 3 ag (ignore) (mmap) ag -i PM_RESUME 1.621368646621704 370
63 linux_literal_casei 1 3 ag (ignore) (mmap) ag -i PM_RESUME 1.5698626041412354 370
64 linux_literal_casei 1 3 ag (ignore) (mmap) ag -i PM_RESUME 1.6105949878692627 370
65 linux_literal_casei 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME 0.8005843162536621 370
66 linux_literal_casei 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME 0.8044955730438232 370
67 linux_literal_casei 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME 0.806922197341919 370
68 linux_literal_casei 1 3 git grep (ignore) git grep -I -n -i PM_RESUME 0.34161829948425293 370 LC_ALL=C
69 linux_literal_casei 1 3 git grep (ignore) git grep -I -n -i PM_RESUME 0.3455958366394043 370 LC_ALL=C
70 linux_literal_casei 1 3 git grep (ignore) git grep -I -n -i PM_RESUME 0.3493361473083496 370 LC_ALL=C
71 linux_literal_casei 1 3 rg (whitelist) rg -n -i --no-ignore -tall PM_RESUME 0.2149522304534912 370
72 linux_literal_casei 1 3 rg (whitelist) rg -n -i --no-ignore -tall PM_RESUME 0.21602368354797363 370
73 linux_literal_casei 1 3 rg (whitelist) rg -n -i --no-ignore -tall PM_RESUME 0.27021098136901855 370
74 linux_literal_casei 1 3 ucg (whitelist) ucg -i PM_RESUME 0.22747421264648438 370
75 linux_literal_casei 1 3 ucg (whitelist) ucg -i PM_RESUME 0.22050881385803223 370
76 linux_literal_casei 1 3 ucg (whitelist) ucg -i PM_RESUME 0.21217584609985352 370
77 linux_literal_default 1 3 rg rg PM_RESUME 0.27482175827026367 16
78 linux_literal_default 1 3 rg rg PM_RESUME 0.2796294689178467 16
79 linux_literal_default 1 3 rg rg PM_RESUME 0.27638936042785645 16
80 linux_literal_default 1 3 ag ag PM_RESUME 1.598384141921997 16
81 linux_literal_default 1 3 ag ag PM_RESUME 1.5849597454071045 16
82 linux_literal_default 1 3 ag ag PM_RESUME 1.6000149250030518 16
83 linux_literal_default 1 3 ucg ucg PM_RESUME 0.2263963222503662 16
84 linux_literal_default 1 3 ucg ucg PM_RESUME 0.21367835998535156 16
85 linux_literal_default 1 3 ucg ucg PM_RESUME 0.21764111518859863 16
86 linux_literal_default 1 3 pt pt PM_RESUME 0.42263340950012207 16
87 linux_literal_default 1 3 pt pt PM_RESUME 0.467041015625 16
88 linux_literal_default 1 3 pt pt PM_RESUME 0.42820048332214355 16
89 linux_literal_default 1 3 sift sift PM_RESUME 0.33421826362609863 16
90 linux_literal_default 1 3 sift sift PM_RESUME 0.35932135581970215 16
91 linux_literal_default 1 3 sift sift PM_RESUME 0.3372631072998047 16
92 linux_literal_default 1 3 git grep git grep PM_RESUME 0.348984956741333 16 LC_ALL=en_US.UTF-8
93 linux_literal_default 1 3 git grep git grep PM_RESUME 0.34420299530029297 16 LC_ALL=en_US.UTF-8
94 linux_literal_default 1 3 git grep git grep PM_RESUME 0.33880615234375 16 LC_ALL=en_US.UTF-8
95 linux_no_literal 1 3 rg (ignore) rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.5833027362823486 490
96 linux_no_literal 1 3 rg (ignore) rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.5783836841583252 490
97 linux_no_literal 1 3 rg (ignore) rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.5806806087493896 490
98 linux_no_literal 1 3 rg (ignore) (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.4163496494293213 490
99 linux_no_literal 1 3 rg (ignore) (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.4040029048919678 490
100 linux_no_literal 1 3 rg (ignore) (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.40265560150146484 490
101 linux_no_literal 1 3 ag (ignore) (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 2.3176910877227783 766
102 linux_no_literal 1 3 ag (ignore) (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 2.3504347801208496 766
103 linux_no_literal 1 3 ag (ignore) (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 2.317542552947998 766
104 linux_no_literal 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 25.821982383728027 491
105 linux_no_literal 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 25.82067561149597 491
106 linux_no_literal 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 25.626302242279053 491
107 linux_no_literal 1 3 git grep (ignore) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 26.349210023880005 490 LC_ALL=en_US.UTF-8
108 linux_no_literal 1 3 git grep (ignore) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 26.34226369857788 490 LC_ALL=en_US.UTF-8
109 linux_no_literal 1 3 git grep (ignore) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 26.340656995773315 490 LC_ALL=en_US.UTF-8
110 linux_no_literal 1 3 git grep (ignore) (ASCII) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 4.14680290222168 490 LC_ALL=C
111 linux_no_literal 1 3 git grep (ignore) (ASCII) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 4.153340578079224 490 LC_ALL=C
112 linux_no_literal 1 3 git grep (ignore) (ASCII) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 4.154819011688232 490 LC_ALL=C
113 linux_no_literal 1 3 rg (whitelist) rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.49768829345703125 419
114 linux_no_literal 1 3 rg (whitelist) rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.5121400356292725 419
115 linux_no_literal 1 3 rg (whitelist) rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.49718427658081055 419
116 linux_no_literal 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.38550543785095215 419
117 linux_no_literal 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.32651591300964355 419
118 linux_no_literal 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.3246915340423584 419
119 linux_no_literal 1 3 ucg (whitelist) (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 1.128183126449585 416
120 linux_no_literal 1 3 ucg (whitelist) (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 1.1255216598510742 416
121 linux_no_literal 1 3 ucg (whitelist) (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 1.1268525123596191 416
122 linux_re_literal_suffix 1 3 rg (ignore) rg -n [A-Z]+_RESUME 0.36306214332580566 1652
123 linux_re_literal_suffix 1 3 rg (ignore) rg -n [A-Z]+_RESUME 0.45077037811279297 1652
124 linux_re_literal_suffix 1 3 rg (ignore) rg -n [A-Z]+_RESUME 0.3804624080657959 1652
125 linux_re_literal_suffix 1 3 ag (ignore) ag -s [A-Z]+_RESUME 1.8995850086212158 1652
126 linux_re_literal_suffix 1 3 ag (ignore) ag -s [A-Z]+_RESUME 1.8897662162780762 1652
127 linux_re_literal_suffix 1 3 ag (ignore) ag -s [A-Z]+_RESUME 1.878380537033081 1652
128 linux_re_literal_suffix 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME 10.48949646949768 1652
129 linux_re_literal_suffix 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME 10.289165735244751 1652
130 linux_re_literal_suffix 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME 10.000468254089355 1652
131 linux_re_literal_suffix 1 3 git grep (ignore) git grep -E -I -n [A-Z]+_RESUME 1.1080453395843506 1652 LC_ALL=C
132 linux_re_literal_suffix 1 3 git grep (ignore) git grep -E -I -n [A-Z]+_RESUME 1.10821533203125 1652 LC_ALL=C
133 linux_re_literal_suffix 1 3 git grep (ignore) git grep -E -I -n [A-Z]+_RESUME 1.105595588684082 1652 LC_ALL=C
134 linux_re_literal_suffix 1 3 rg (whitelist) rg -n --no-ignore -tall [A-Z]+_RESUME 0.2073357105255127 1630
135 linux_re_literal_suffix 1 3 rg (whitelist) rg -n --no-ignore -tall [A-Z]+_RESUME 0.20552492141723633 1630
136 linux_re_literal_suffix 1 3 rg (whitelist) rg -n --no-ignore -tall [A-Z]+_RESUME 0.2061319351196289 1630
137 linux_re_literal_suffix 1 3 ucg (whitelist) ucg --nosmart-case [A-Z]+_RESUME 0.3013310432434082 1630
138 linux_re_literal_suffix 1 3 ucg (whitelist) ucg --nosmart-case [A-Z]+_RESUME 0.3005218505859375 1630
139 linux_re_literal_suffix 1 3 ucg (whitelist) ucg --nosmart-case [A-Z]+_RESUME 0.29984378814697266 1630
140 linux_unicode_greek 1 3 rg rg -n \p{Greek} 0.4162716865539551 23
141 linux_unicode_greek 1 3 rg rg -n \p{Greek} 0.47885966300964355 23
142 linux_unicode_greek 1 3 rg rg -n \p{Greek} 0.5135962963104248 23
143 linux_unicode_greek 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek} 7.570494651794434 23
144 linux_unicode_greek 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek} 7.790151596069336 23
145 linux_unicode_greek 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek} 7.783358812332153 23
146 linux_unicode_greek_casei 1 3 rg rg -n -i \p{Greek} 0.4370443820953369 103
147 linux_unicode_greek_casei 1 3 rg rg -n -i \p{Greek} 0.40680766105651855 103
148 linux_unicode_greek_casei 1 3 rg rg -n -i \p{Greek} 0.4011569023132324 103
149 linux_unicode_greek_casei 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek} 0.002422809600830078
150 linux_unicode_greek_casei 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek} 0.002414226531982422
151 linux_unicode_greek_casei 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek} 0.002293109893798828
152 linux_unicode_word 1 3 rg (ignore) rg -n \wAh 0.44771265983581543 186
153 linux_unicode_word 1 3 rg (ignore) rg -n \wAh 0.3006107807159424 186
154 linux_unicode_word 1 3 rg (ignore) rg -n \wAh 0.3026111125946045 186
155 linux_unicode_word 1 3 rg (ignore) (ASCII) rg -n (?-u)\wAh 0.43827080726623535 174
156 linux_unicode_word 1 3 rg (ignore) (ASCII) rg -n (?-u)\wAh 0.2931697368621826 174
157 linux_unicode_word 1 3 rg (ignore) (ASCII) rg -n (?-u)\wAh 0.33072638511657715 174
158 linux_unicode_word 1 3 ag (ignore) (ASCII) ag -s \wAh 1.7645132541656494 174
159 linux_unicode_word 1 3 ag (ignore) (ASCII) ag -s \wAh 1.7730333805084229 174
160 linux_unicode_word 1 3 ag (ignore) (ASCII) ag -s \wAh 1.773383378982544 174
161 linux_unicode_word 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh 10.872124671936035 174
162 linux_unicode_word 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh 11.147738456726074 174
163 linux_unicode_word 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh 11.029243469238281 174
164 linux_unicode_word 1 3 git grep (ignore) git grep -E -I -n \wAh 13.047154664993286 186 LC_ALL=en_US.UTF-8
165 linux_unicode_word 1 3 git grep (ignore) git grep -E -I -n \wAh 13.025037288665771 186 LC_ALL=en_US.UTF-8
166 linux_unicode_word 1 3 git grep (ignore) git grep -E -I -n \wAh 13.081012487411499 186 LC_ALL=en_US.UTF-8
167 linux_unicode_word 1 3 git grep (ignore) (ASCII) git grep -E -I -n \wAh 2.98722767829895 174 LC_ALL=C
168 linux_unicode_word 1 3 git grep (ignore) (ASCII) git grep -E -I -n \wAh 2.987990379333496 174 LC_ALL=C
169 linux_unicode_word 1 3 git grep (ignore) (ASCII) git grep -E -I -n \wAh 2.988698959350586 174 LC_ALL=C
170 linux_unicode_word 1 3 rg (whitelist) rg -n --no-ignore -tall \wAh 0.21961355209350586 180
171 linux_unicode_word 1 3 rg (whitelist) rg -n --no-ignore -tall \wAh 0.2884254455566406 180
172 linux_unicode_word 1 3 rg (whitelist) rg -n --no-ignore -tall \wAh 0.21905040740966797 180
173 linux_unicode_word 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\wAh 0.23966765403747559 168
174 linux_unicode_word 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\wAh 0.21801042556762695 168
175 linux_unicode_word 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\wAh 0.21909880638122559 168
176 linux_unicode_word 1 3 ucg (ASCII) ucg --nosmart-case \wAh 0.2259504795074463 168
177 linux_unicode_word 1 3 ucg (ASCII) ucg --nosmart-case \wAh 0.22269177436828613 168
178 linux_unicode_word 1 3 ucg (ASCII) ucg --nosmart-case \wAh 0.2259974479675293 168
179 linux_word 1 3 rg (ignore) rg -n -w PM_RESUME 0.34968090057373047 6
180 linux_word 1 3 rg (ignore) rg -n -w PM_RESUME 0.28850769996643066 6
181 linux_word 1 3 rg (ignore) rg -n -w PM_RESUME 0.34809160232543945 6
182 linux_word 1 3 ag (ignore) ag -s -w PM_RESUME 1.6134660243988037 6
183 linux_word 1 3 ag (ignore) ag -s -w PM_RESUME 1.59847092628479 6
184 linux_word 1 3 ag (ignore) ag -s -w PM_RESUME 1.581369161605835 6
185 linux_word 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME 7.644887208938599 6
186 linux_word 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME 7.8782219886779785 6
187 linux_word 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME 7.754150152206421 6
188 linux_word 1 3 git grep (ignore) git grep -E -I -n -w PM_RESUME 0.34302353858947754 6 LC_ALL=C
189 linux_word 1 3 git grep (ignore) git grep -E -I -n -w PM_RESUME 0.33672142028808594 6 LC_ALL=C
190 linux_word 1 3 git grep (ignore) git grep -E -I -n -w PM_RESUME 0.35193610191345215 6 LC_ALL=C
191 linux_word 1 3 rg (whitelist) rg -n -w --no-ignore -tall PM_RESUME 0.33329272270202637 6
192 linux_word 1 3 rg (whitelist) rg -n -w --no-ignore -tall PM_RESUME 0.25751829147338867 6
193 linux_word 1 3 rg (whitelist) rg -n -w --no-ignore -tall PM_RESUME 0.21761608123779297 6
194 linux_word 1 3 ucg (whitelist) ucg --nosmart-case -w PM_RESUME 0.22014284133911133 6
195 linux_word 1 3 ucg (whitelist) ucg --nosmart-case -w PM_RESUME 0.22314929962158203 6
196 linux_word 1 3 ucg (whitelist) ucg --nosmart-case -w PM_RESUME 0.2202434539794922 6
197 subtitles_en_alternate 1 3 rg (lines) rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.622809886932373 848
198 subtitles_en_alternate 1 3 rg (lines) rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6181182861328125 848
199 subtitles_en_alternate 1 3 rg (lines) rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6205663681030273 848
200 subtitles_en_alternate 1 3 ag (lines) ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.7565691471099854 848
201 subtitles_en_alternate 1 3 ag (lines) ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.7561769485473633 848
202 subtitles_en_alternate 1 3 ag (lines) ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.7559969425201416 848
203 subtitles_en_alternate 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.4493463039398193 848
204 subtitles_en_alternate 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.44877028465271 848
205 subtitles_en_alternate 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.4433801174163818 848
206 subtitles_en_alternate 1 3 grep (lines) grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.4114174842834473 848 LC_ALL=C
207 subtitles_en_alternate 1 3 grep (lines) grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.411625862121582 848 LC_ALL=C
208 subtitles_en_alternate 1 3 grep (lines) grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.408623456954956 848 LC_ALL=C
209 subtitles_en_alternate 1 3 rg rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.2900726795196533 848
210 subtitles_en_alternate 1 3 rg rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.2905848026275635 848
211 subtitles_en_alternate 1 3 rg rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.2903940677642822 848
212 subtitles_en_alternate 1 3 grep grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.9546515941619873 848 LC_ALL=C
213 subtitles_en_alternate 1 3 grep grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.955279588699341 848 LC_ALL=C
214 subtitles_en_alternate 1 3 grep grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.954089403152466 848 LC_ALL=C
215 subtitles_en_alternate_casei 1 3 ag (ASCII) ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 5.169135332107544 862
216 subtitles_en_alternate_casei 1 3 ag (ASCII) ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 5.174601078033447 862
217 subtitles_en_alternate_casei 1 3 ag (ASCII) ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 5.1684675216674805 862
218 subtitles_en_alternate_casei 1 3 ucg (ASCII) ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.4171736240386963 862
219 subtitles_en_alternate_casei 1 3 ucg (ASCII) ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.4158167839050293 862
220 subtitles_en_alternate_casei 1 3 ucg (ASCII) ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.4186513423919678 862
221 subtitles_en_alternate_casei 1 3 grep (ASCII) grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.531639575958252 862 LC_ALL=C
222 subtitles_en_alternate_casei 1 3 grep (ASCII) grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.526550054550171 862 LC_ALL=C
223 subtitles_en_alternate_casei 1 3 grep (ASCII) grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.528509140014648 862 LC_ALL=C
224 subtitles_en_alternate_casei 1 3 rg rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.722398281097412 862
225 subtitles_en_alternate_casei 1 3 rg rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.7225935459136963 862
226 subtitles_en_alternate_casei 1 3 rg rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.7222185134887695 862
227 subtitles_en_alternate_casei 1 3 grep grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 5.12151837348938 862 LC_ALL=en_US.UTF-8
228 subtitles_en_alternate_casei 1 3 grep grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 5.119963884353638 862 LC_ALL=en_US.UTF-8
229 subtitles_en_alternate_casei 1 3 grep grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 5.121079683303833 862 LC_ALL=en_US.UTF-8
230 subtitles_en_literal 1 3 rg rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.2684764862060547 629
231 subtitles_en_literal 1 3 rg rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.26811957359313965 629
232 subtitles_en_literal 1 3 rg rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.2684173583984375 629
233 subtitles_en_literal 1 3 pt pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.435128688812256 629
234 subtitles_en_literal 1 3 pt pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.4362881183624268 629
235 subtitles_en_literal 1 3 pt pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.4399220943450928 629
236 subtitles_en_literal 1 3 sift sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.32662391662597656 629
237 subtitles_en_literal 1 3 sift sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.3277275562286377 629
238 subtitles_en_literal 1 3 sift sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.32798290252685547 629
239 subtitles_en_literal 1 3 grep grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.520500659942627 629 LC_ALL=C
240 subtitles_en_literal 1 3 grep grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5191032886505127 629 LC_ALL=C
241 subtitles_en_literal 1 3 grep grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5171597003936768 629 LC_ALL=C
242 subtitles_en_literal 1 3 rg (lines) rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.595801830291748 629
243 subtitles_en_literal 1 3 rg (lines) rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5954360961914062 629
244 subtitles_en_literal 1 3 rg (lines) rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5945618152618408 629
245 subtitles_en_literal 1 3 ag (lines) ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.7291676998138428 629
246 subtitles_en_literal 1 3 ag (lines) ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.730966329574585 629
247 subtitles_en_literal 1 3 ag (lines) ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.728854179382324 629
248 subtitles_en_literal 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.775996208190918 629
249 subtitles_en_literal 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.7760195732116699 629
250 subtitles_en_literal 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.7763564586639404 629
251 subtitles_en_literal 1 3 pt (lines) pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.433366060256958 629
252 subtitles_en_literal 1 3 pt (lines) pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.4338581562042236 629
253 subtitles_en_literal 1 3 pt (lines) pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 3.435924768447876 629
254 subtitles_en_literal 1 3 sift (lines) sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.7586827278137207 629
255 subtitles_en_literal 1 3 sift (lines) sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.7590317726135254 629
256 subtitles_en_literal 1 3 sift (lines) sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.754432201385498 629
257 subtitles_en_literal 1 3 grep (lines) grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.9726488590240479 629 LC_ALL=C
258 subtitles_en_literal 1 3 grep (lines) grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.9699857234954834 629 LC_ALL=C
259 subtitles_en_literal 1 3 grep (lines) grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.9714112281799316 629 LC_ALL=C
260 subtitles_en_literal_casei 1 3 rg rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.36658453941345215 642
261 subtitles_en_literal_casei 1 3 rg rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.3654778003692627 642
262 subtitles_en_literal_casei 1 3 rg rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.36565113067626953 642
263 subtitles_en_literal_casei 1 3 grep grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.0890116691589355 642 LC_ALL=en_US.UTF-8
264 subtitles_en_literal_casei 1 3 grep grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.08124852180481 642 LC_ALL=en_US.UTF-8
265 subtitles_en_literal_casei 1 3 grep grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.0796849727630615 642 LC_ALL=en_US.UTF-8
266 subtitles_en_literal_casei 1 3 grep (ASCII) grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6151647567749023 642 LC_ALL=C
267 subtitles_en_literal_casei 1 3 grep (ASCII) grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6141552925109863 642 LC_ALL=C
268 subtitles_en_literal_casei 1 3 grep (ASCII) grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6132988929748535 642 LC_ALL=C
269 subtitles_en_literal_casei 1 3 rg (lines) rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6962459087371826 642
270 subtitles_en_literal_casei 1 3 rg (lines) rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6945579051971436 642
271 subtitles_en_literal_casei 1 3 rg (lines) rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.693866491317749 642
272 subtitles_en_literal_casei 1 3 ag (lines) (ASCII) ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.771639823913574 642
273 subtitles_en_literal_casei 1 3 ag (lines) (ASCII) ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.772296190261841 642
274 subtitles_en_literal_casei 1 3 ag (lines) (ASCII) ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.7712018489837646 642
275 subtitles_en_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.8068230152130127 642
276 subtitles_en_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.80411696434021 642
277 subtitles_en_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.8038516044616699 642
278 subtitles_en_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5951778888702393 629
279 subtitles_en_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5971941947937012 629
280 subtitles_en_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5952184200286865 629
281 subtitles_en_literal_word 1 3 ag (ASCII) ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.7292284965515137 629
282 subtitles_en_literal_word 1 3 ag (ASCII) ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.728681802749634 629
283 subtitles_en_literal_word 1 3 ag (ASCII) ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.7315311431884766 629
284 subtitles_en_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.784024715423584 629
285 subtitles_en_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.780540943145752 629
286 subtitles_en_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.7772648334503174 629
287 subtitles_en_literal_word 1 3 grep (ASCII) grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.9744353294372559 629 LC_ALL=C
288 subtitles_en_literal_word 1 3 grep (ASCII) grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.9781327247619629 629 LC_ALL=C
289 subtitles_en_literal_word 1 3 grep (ASCII) grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.9798097610473633 629 LC_ALL=C
290 subtitles_en_literal_word 1 3 rg rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5965189933776855 629
291 subtitles_en_literal_word 1 3 rg rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5960156917572021 629
292 subtitles_en_literal_word 1 3 rg rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.5975723266601562 629
293 subtitles_en_literal_word 1 3 grep grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.9818971157073975 629 LC_ALL=en_US.UTF-8
294 subtitles_en_literal_word 1 3 grep grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.9785251617431641 629 LC_ALL=en_US.UTF-8
295 subtitles_en_literal_word 1 3 grep grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.977081298828125 629 LC_ALL=en_US.UTF-8
296 subtitles_en_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.7750890254974365 13
297 subtitles_en_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.774017333984375 13
298 subtitles_en_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.783200740814209 13
299 subtitles_en_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.5396409034729004 13
300 subtitles_en_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.5404820442199707 13
301 subtitles_en_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 2.5400590896606445 13
302 subtitles_en_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 10.072888612747192 48
303 subtitles_en_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 10.075153350830078 48
304 subtitles_en_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 10.0713791847229 48
305 subtitles_en_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 7.734791278839111 13
306 subtitles_en_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 7.7345263957977295 13
307 subtitles_en_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 7.73199462890625 13
308 subtitles_en_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.411367416381836 13 LC_ALL=C
309 subtitles_en_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.41072940826416 13 LC_ALL=C
310 subtitles_en_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.414730072021484 13 LC_ALL=C
311 subtitles_en_surrounding_words 1 3 rg rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6052529811859131 317
312 subtitles_en_surrounding_words 1 3 rg rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6049232482910156 317
313 subtitles_en_surrounding_words 1 3 rg rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6045565605163574 317
314 subtitles_en_surrounding_words 1 3 grep grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.2849924564361572 317 LC_ALL=en_US.UTF-8
315 subtitles_en_surrounding_words 1 3 grep grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.2837722301483154 317 LC_ALL=en_US.UTF-8
316 subtitles_en_surrounding_words 1 3 grep grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.2847650051116943 317 LC_ALL=en_US.UTF-8
317 subtitles_en_surrounding_words 1 3 rg (ASCII) rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6005992889404297 317
318 subtitles_en_surrounding_words 1 3 rg (ASCII) rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.600543737411499 317
319 subtitles_en_surrounding_words 1 3 rg (ASCII) rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 0.6009273529052734 317
320 subtitles_en_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 11.664374113082886 323
321 subtitles_en_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 11.674306869506836 323
322 subtitles_en_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 11.657484769821167 323
323 subtitles_en_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.650290012359619 317
324 subtitles_en_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.651855707168579 317
325 subtitles_en_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 4.649921417236328 317
326 subtitles_en_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.2745037078857422 317 LC_ALL=C
327 subtitles_en_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.275665521621704 317 LC_ALL=C
328 subtitles_en_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en 1.273988962173462 317 LC_ALL=C
329 subtitles_ru_alternate 1 3 rg (lines) rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.9031155109405518 691
330 subtitles_ru_alternate 1 3 rg (lines) rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.9021081924438477 691
331 subtitles_ru_alternate 1 3 rg (lines) rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.9028818607330322 691
332 subtitles_ru_alternate 1 3 ag (lines) ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 5.8895978927612305 691
333 subtitles_ru_alternate 1 3 ag (lines) ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 5.891357660293579 691
334 subtitles_ru_alternate 1 3 ag (lines) ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 5.892467975616455 691
335 subtitles_ru_alternate 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.7517757415771484 691
336 subtitles_ru_alternate 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.7550888061523438 691
337 subtitles_ru_alternate 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.7555651664733887 691
338 subtitles_ru_alternate 1 3 grep (lines) grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.51417875289917 691 LC_ALL=C
339 subtitles_ru_alternate 1 3 grep (lines) grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.512972116470337 691 LC_ALL=C
340 subtitles_ru_alternate 1 3 grep (lines) grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.507266521453857 691 LC_ALL=C
341 subtitles_ru_alternate 1 3 rg rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.300950288772583 691
342 subtitles_ru_alternate 1 3 rg rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.2987852096557617 691
343 subtitles_ru_alternate 1 3 rg rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.3024635314941406 691
344 subtitles_ru_alternate 1 3 grep grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 7.983739137649536 691 LC_ALL=C
345 subtitles_ru_alternate 1 3 grep grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 7.988446950912476 691 LC_ALL=C
346 subtitles_ru_alternate 1 3 grep grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 7.979671478271484 691 LC_ALL=C
347 subtitles_ru_alternate_casei 1 3 ag (ASCII) ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 5.889382362365723 691
348 subtitles_ru_alternate_casei 1 3 ag (ASCII) ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 5.902577877044678 691
349 subtitles_ru_alternate_casei 1 3 ag (ASCII) ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 5.890571355819702 691
350 subtitles_ru_alternate_casei 1 3 ucg (ASCII) ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.7548162937164307 691
351 subtitles_ru_alternate_casei 1 3 ucg (ASCII) ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.747791051864624 691
352 subtitles_ru_alternate_casei 1 3 ucg (ASCII) ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.7396674156188965 691
353 subtitles_ru_alternate_casei 1 3 grep (ASCII) grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.58053183555603 691 LC_ALL=C
354 subtitles_ru_alternate_casei 1 3 grep (ASCII) grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.594751596450806 691 LC_ALL=C
355 subtitles_ru_alternate_casei 1 3 grep (ASCII) grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.561670541763306 691 LC_ALL=C
356 subtitles_ru_alternate_casei 1 3 rg rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.833597183227539 735
357 subtitles_ru_alternate_casei 1 3 rg rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.831137180328369 735
358 subtitles_ru_alternate_casei 1 3 rg rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.830361843109131 735
359 subtitles_ru_alternate_casei 1 3 grep grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.723876953125 735 LC_ALL=en_US.UTF-8
360 subtitles_ru_alternate_casei 1 3 grep grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.723239183425903 735 LC_ALL=en_US.UTF-8
361 subtitles_ru_alternate_casei 1 3 grep grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.722000360488892 735 LC_ALL=en_US.UTF-8
362 subtitles_ru_literal 1 3 rg rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.3252851963043213 583
363 subtitles_ru_literal 1 3 rg rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.3270294666290283 583
364 subtitles_ru_literal 1 3 rg rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.32680773735046387 583
365 subtitles_ru_literal 1 3 pt pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 12.932488679885864 583
366 subtitles_ru_literal 1 3 pt pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 12.91330337524414 583
367 subtitles_ru_literal 1 3 pt pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 12.911381006240845 583
368 subtitles_ru_literal 1 3 sift sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 16.438587427139282 583
369 subtitles_ru_literal 1 3 sift sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 16.412389755249023 583
370 subtitles_ru_literal 1 3 sift sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 16.412444353103638 583
371 subtitles_ru_literal 1 3 grep grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7865939140319824 583 LC_ALL=C
372 subtitles_ru_literal 1 3 grep grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7889957427978516 583 LC_ALL=C
373 subtitles_ru_literal 1 3 grep grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7923679351806641 583 LC_ALL=C
374 subtitles_ru_literal 1 3 rg (lines) rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9255633354187012 583
375 subtitles_ru_literal 1 3 rg (lines) rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9285938739776611 583
376 subtitles_ru_literal 1 3 rg (lines) rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9274048805236816 583
377 subtitles_ru_literal 1 3 ag (lines) ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.4811036586761475 583
378 subtitles_ru_literal 1 3 ag (lines) ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.4785168170928955 583
379 subtitles_ru_literal 1 3 ag (lines) ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.484618186950684 583
380 subtitles_ru_literal 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.7743628025054932 583
381 subtitles_ru_literal 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.7731456756591797 583
382 subtitles_ru_literal 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.7749128341674805 583
383 subtitles_ru_literal 1 3 pt (lines) pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 12.931540250778198 583
384 subtitles_ru_literal 1 3 pt (lines) pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 12.935162782669067 583
385 subtitles_ru_literal 1 3 pt (lines) pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 12.949711561203003 583
386 subtitles_ru_literal 1 3 sift (lines) sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 17.183809995651245 583
387 subtitles_ru_literal 1 3 sift (lines) sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 17.19060492515564 583
388 subtitles_ru_literal 1 3 sift (lines) sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 17.17626404762268 583
389 subtitles_ru_literal 1 3 grep (lines) grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.3023960590362549 583 LC_ALL=C
390 subtitles_ru_literal 1 3 grep (lines) grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.2992589473724365 583 LC_ALL=C
391 subtitles_ru_literal 1 3 grep (lines) grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.299330711364746 583 LC_ALL=C
392 subtitles_ru_literal_casei 1 3 rg rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.1320264339447021 604
393 subtitles_ru_literal_casei 1 3 rg rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.1323668956756592 604
394 subtitles_ru_literal_casei 1 3 rg rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.1354515552520752 604
395 subtitles_ru_literal_casei 1 3 grep grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.194744348526001 604 LC_ALL=en_US.UTF-8
396 subtitles_ru_literal_casei 1 3 grep grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.190656423568726 604 LC_ALL=en_US.UTF-8
397 subtitles_ru_literal_casei 1 3 grep grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 8.18506383895874 604 LC_ALL=en_US.UTF-8
398 subtitles_ru_literal_casei 1 3 grep (ASCII) grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7826528549194336 583 LC_ALL=C
399 subtitles_ru_literal_casei 1 3 grep (ASCII) grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7846219539642334 583 LC_ALL=C
400 subtitles_ru_literal_casei 1 3 grep (ASCII) grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7846999168395996 583 LC_ALL=C
401 subtitles_ru_literal_casei 1 3 rg (lines) rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.734788179397583 604
402 subtitles_ru_literal_casei 1 3 rg (lines) rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.7333040237426758 604
403 subtitles_ru_literal_casei 1 3 rg (lines) rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.731860637664795 604
404 subtitles_ru_literal_casei 1 3 ag (lines) (ASCII) ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7297205924987793
405 subtitles_ru_literal_casei 1 3 ag (lines) (ASCII) ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7314808368682861
406 subtitles_ru_literal_casei 1 3 ag (lines) (ASCII) ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7289514541625977
407 subtitles_ru_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.7773914337158203 583
408 subtitles_ru_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.774536371231079 583
409 subtitles_ru_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.7740859985351562 583
410 subtitles_ru_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.3252553939819336
411 subtitles_ru_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.32543301582336426
412 subtitles_ru_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.32512736320495605
413 subtitles_ru_literal_word 1 3 ag (ASCII) ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7519562244415283
414 subtitles_ru_literal_word 1 3 ag (ASCII) ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.752692699432373
415 subtitles_ru_literal_word 1 3 ag (ASCII) ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.7524521350860596
416 subtitles_ru_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.7868170738220215 583
417 subtitles_ru_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.7786612510681152 583
418 subtitles_ru_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.776214838027954 583
419 subtitles_ru_literal_word 1 3 grep (ASCII) grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.303652286529541 583 LC_ALL=C
420 subtitles_ru_literal_word 1 3 grep (ASCII) grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.3012151718139648 583 LC_ALL=C
421 subtitles_ru_literal_word 1 3 grep (ASCII) grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.307457685470581 583 LC_ALL=C
422 subtitles_ru_literal_word 1 3 rg rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9280951023101807 579
423 subtitles_ru_literal_word 1 3 rg rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9285900592803955 579
424 subtitles_ru_literal_word 1 3 rg rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9288535118103027 579
425 subtitles_ru_literal_word 1 3 grep grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.3026466369628906 579 LC_ALL=en_US.UTF-8
426 subtitles_ru_literal_word 1 3 grep grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.3016819953918457 579 LC_ALL=en_US.UTF-8
427 subtitles_ru_literal_word 1 3 grep grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.3006587028503418 579 LC_ALL=en_US.UTF-8
428 subtitles_ru_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.895586729049683 41
429 subtitles_ru_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.914353132247925 41
430 subtitles_ru_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 4.902980327606201 41
431 subtitles_ru_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 3.972637891769409
432 subtitles_ru_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 3.9723849296569824
433 subtitles_ru_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 3.9723057746887207
434 subtitles_ru_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.3936586380004883
435 subtitles_ru_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.3987748622894287
436 subtitles_ru_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.393911361694336
437 subtitles_ru_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.8932065963745117
438 subtitles_ru_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.8977222442626953
439 subtitles_ru_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.893040895462036
440 subtitles_ru_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.4844722747802734 LC_ALL=C
441 subtitles_ru_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.485093116760254 LC_ALL=C
442 subtitles_ru_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.482459306716919 LC_ALL=C
443 subtitles_ru_surrounding_words 1 3 rg rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9564735889434814 278
444 subtitles_ru_surrounding_words 1 3 rg rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9561436176300049 278
445 subtitles_ru_surrounding_words 1 3 rg rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 0.9558789730072021 278
446 subtitles_ru_surrounding_words 1 3 grep grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.6620113849639893 278 LC_ALL=en_US.UTF-8
447 subtitles_ru_surrounding_words 1 3 grep grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.6624438762664795 278 LC_ALL=en_US.UTF-8
448 subtitles_ru_surrounding_words 1 3 grep grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.6610260009765625 278 LC_ALL=en_US.UTF-8
449 subtitles_ru_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.4094629287719727
450 subtitles_ru_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.409822702407837
451 subtitles_ru_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.4094691276550293
452 subtitles_ru_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.866976261138916
453 subtitles_ru_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.8666067123413086
454 subtitles_ru_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 2.865297317504883
455 subtitles_ru_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.602109670639038 LC_ALL=C
456 subtitles_ru_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.598329782485962 LC_ALL=C
457 subtitles_ru_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru 1.5975282192230225 LC_ALL=C

View File

@@ -0,0 +1,226 @@
linux_alternates (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
-------------------------------------------------------------------------
rg (ignore) 0.322 +/- 0.042 (lines: 68)
ag (ignore) 1.754 +/- 0.006 (lines: 68)
git grep (ignore) 0.502 +/- 0.004 (lines: 68)
rg (whitelist)* 0.197 +/- 0.001 (lines: 68)*
ucg (whitelist) 0.217 +/- 0.004 (lines: 68)
linux_alternates_casei (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
-------------------------------------------------------------------------------
rg (ignore) 0.372 +/- 0.096 (lines: 160)
ag (ignore) 1.965 +/- 0.009 (lines: 160)
git grep (ignore) 2.022 +/- 0.001 (lines: 160)
rg (whitelist)* 0.222 +/- 0.001 (lines: 160)*
ucg (whitelist) 0.524 +/- 0.005 (lines: 160)
linux_literal (pattern: PM_RESUME)
----------------------------------
rg (ignore) 0.348 +/- 0.054 (lines: 16)
rg (ignore) (mmap) 1.597 +/- 0.013 (lines: 16)
ag (ignore) (mmap) 1.590 +/- 0.003 (lines: 16)
pt (ignore) 0.455 +/- 0.015 (lines: 16)
sift (ignore) 0.630 +/- 0.001 (lines: 16)
git grep (ignore) 0.344 +/- 0.004 (lines: 16)
rg (whitelist)* 0.253 +/- 0.077 (lines: 16)
ucg (whitelist) 0.222 +/- 0.005 (lines: 16)*
linux_literal_casei (pattern: PM_RESUME)
----------------------------------------
rg (ignore) 0.423 +/- 0.118 (lines: 370)
rg (ignore) (mmap) 1.615 +/- 0.010 (lines: 370)
ag (ignore) (mmap) 1.601 +/- 0.027 (lines: 370)
sift (ignore) 0.804 +/- 0.003 (lines: 370)
git grep (ignore) 0.346 +/- 0.004 (lines: 370)
rg (whitelist) 0.234 +/- 0.032 (lines: 370)
ucg (whitelist)* 0.220 +/- 0.008 (lines: 370)*
linux_literal_default (pattern: PM_RESUME)
------------------------------------------
rg 0.277 +/- 0.002 (lines: 16)
ag 1.594 +/- 0.008 (lines: 16)
ucg* 0.219 +/- 0.007 (lines: 16)*
pt 0.439 +/- 0.024 (lines: 16)
sift 0.344 +/- 0.014 (lines: 16)
git grep 0.344 +/- 0.005 (lines: 16)
linux_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
-----------------------------------------------------------------
rg (ignore) 0.581 +/- 0.002 (lines: 490)
rg (ignore) (ASCII) 0.408 +/- 0.008 (lines: 490)
ag (ignore) (ASCII) 2.329 +/- 0.019 (lines: 766)
sift (ignore) (ASCII) 25.756 +/- 0.113 (lines: 491)
git grep (ignore) 26.344 +/- 0.005 (lines: 490)
git grep (ignore) (ASCII) 4.152 +/- 0.004 (lines: 490)
rg (whitelist) 0.502 +/- 0.008 (lines: 419)
rg (whitelist) (ASCII)* 0.346 +/- 0.035 (lines: 419)*
ucg (whitelist) (ASCII) 1.127 +/- 0.001 (lines: 416)
linux_re_literal_suffix (pattern: [A-Z]+_RESUME)
------------------------------------------------
rg (ignore) 0.398 +/- 0.046 (lines: 1652)
ag (ignore) 1.889 +/- 0.011 (lines: 1652)
sift (ignore) 10.260 +/- 0.246 (lines: 1652)
git grep (ignore) 1.107 +/- 0.001 (lines: 1652)
rg (whitelist)* 0.206 +/- 0.001 (lines: 1630)*
ucg (whitelist) 0.301 +/- 0.001 (lines: 1630)
linux_unicode_greek (pattern: \p{Greek})
----------------------------------------
rg* 0.470 +/- 0.049 (lines: 23)*
sift 7.715 +/- 0.125 (lines: 23)
linux_unicode_greek_casei (pattern: \p{Greek})
----------------------------------------------
rg 0.415 +/- 0.019 (lines: 103)
sift* 0.002 +/- 0.000 (lines: 0)*
linux_unicode_word (pattern: \wAh)
----------------------------------
rg (ignore) 0.350 +/- 0.084 (lines: 186)
rg (ignore) (ASCII) 0.354 +/- 0.075 (lines: 174)
ag (ignore) (ASCII) 1.770 +/- 0.005 (lines: 174)
sift (ignore) (ASCII) 11.016 +/- 0.138 (lines: 174)
git grep (ignore) 13.051 +/- 0.028 (lines: 186)
git grep (ignore) (ASCII) 2.988 +/- 0.001 (lines: 174)
rg (whitelist) 0.242 +/- 0.040 (lines: 180)
rg (whitelist) (ASCII)* 0.226 +/- 0.012 (lines: 168)
ucg (ASCII) 0.225 +/- 0.002 (lines: 168)*
linux_word (pattern: PM_RESUME)
-------------------------------
rg (ignore) 0.329 +/- 0.035 (lines: 6)
ag (ignore) 1.598 +/- 0.016 (lines: 6)
sift (ignore) 7.759 +/- 0.117 (lines: 6)
git grep (ignore) 0.344 +/- 0.008 (lines: 6)
rg (whitelist)* 0.269 +/- 0.059 (lines: 6)
ucg (whitelist) 0.221 +/- 0.002 (lines: 6)*
subtitles_en_alternate (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
---------------------------------------------------------------------------------------------------------------
rg (lines) 0.620 +/- 0.002 (lines: 848)
ag (lines) 3.756 +/- 0.000 (lines: 848)
ucg (lines) 1.447 +/- 0.003 (lines: 848)
grep (lines) 3.411 +/- 0.002 (lines: 848)
rg* 0.290 +/- 0.000 (lines: 848)*
grep 2.955 +/- 0.001 (lines: 848)
subtitles_en_alternate_casei (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
---------------------------------------------------------------------------------------------------------------------
ag (ASCII) 5.171 +/- 0.003 (lines: 862)
ucg (ASCII) 3.417 +/- 0.001 (lines: 862)
grep (ASCII) 4.529 +/- 0.003 (lines: 862)
rg* 2.722 +/- 0.000 (lines: 862)*
grep 5.121 +/- 0.001 (lines: 862)
subtitles_en_literal (pattern: Sherlock Holmes)
-----------------------------------------------
rg* 0.268 +/- 0.000 (lines: 629)*
pt 3.437 +/- 0.003 (lines: 629)
sift 0.327 +/- 0.001 (lines: 629)
grep 0.519 +/- 0.002 (lines: 629)
rg (lines) 0.595 +/- 0.001 (lines: 629)
ag (lines) 2.730 +/- 0.001 (lines: 629)
ucg (lines) 0.776 +/- 0.000 (lines: 629)
pt (lines) 3.434 +/- 0.001 (lines: 629)
sift (lines) 0.757 +/- 0.003 (lines: 629)
grep (lines) 0.971 +/- 0.001 (lines: 629)
subtitles_en_literal_casei (pattern: Sherlock Holmes)
-----------------------------------------------------
rg* 0.366 +/- 0.001 (lines: 642)*
grep 4.083 +/- 0.005 (lines: 642)
grep (ASCII) 0.614 +/- 0.001 (lines: 642)
rg (lines) 0.695 +/- 0.001 (lines: 642)
ag (lines) (ASCII) 2.772 +/- 0.001 (lines: 642)
ucg (lines) (ASCII) 0.805 +/- 0.002 (lines: 642)
subtitles_en_literal_word (pattern: Sherlock Holmes)
----------------------------------------------------
rg (ASCII)* 0.596 +/- 0.001 (lines: 629)*
ag (ASCII) 2.730 +/- 0.002 (lines: 629)
ucg (ASCII) 0.781 +/- 0.003 (lines: 629)
grep (ASCII) 0.977 +/- 0.003 (lines: 629)
rg 0.597 +/- 0.001 (lines: 629)
grep 0.979 +/- 0.002 (lines: 629)
subtitles_en_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
----------------------------------------------------------------------------------------
rg 2.777 +/- 0.005 (lines: 13)
rg (ASCII)* 2.540 +/- 0.000 (lines: 13)*
ag (ASCII) 10.073 +/- 0.002 (lines: 48)
ucg (ASCII) 7.734 +/- 0.002 (lines: 13)
grep (ASCII) 4.412 +/- 0.002 (lines: 13)
subtitles_en_surrounding_words (pattern: \w+\s+Holmes\s+\w+)
------------------------------------------------------------
rg 0.605 +/- 0.000 (lines: 317)
grep 1.285 +/- 0.001 (lines: 317)
rg (ASCII)* 0.601 +/- 0.000 (lines: 317)*
ag (ASCII) 11.665 +/- 0.008 (lines: 323)
ucg (ASCII) 4.651 +/- 0.001 (lines: 317)
grep (ASCII) 1.275 +/- 0.001 (lines: 317)
subtitles_ru_alternate (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
-----------------------------------------------------------------------------------------------------------
rg (lines) 1.903 +/- 0.001 (lines: 691)
ag (lines) 5.891 +/- 0.001 (lines: 691)
ucg (lines) 2.754 +/- 0.002 (lines: 691)
grep (lines) 8.511 +/- 0.004 (lines: 691)
rg* 1.301 +/- 0.002 (lines: 691)*
grep 7.984 +/- 0.004 (lines: 691)
subtitles_ru_alternate_casei (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
-----------------------------------------------------------------------------------------------------------------
ag (ASCII) 5.894 +/- 0.007 (lines: 691)
ucg (ASCII)* 2.747 +/- 0.008 (lines: 691)*
grep (ASCII) 8.579 +/- 0.017 (lines: 691)
rg 4.832 +/- 0.002 (lines: 735)
grep 8.723 +/- 0.001 (lines: 735)
subtitles_ru_literal (pattern: Шерлок Холмс)
--------------------------------------------
rg* 0.326 +/- 0.001 (lines: 583)*
pt 12.919 +/- 0.012 (lines: 583)
sift 16.421 +/- 0.015 (lines: 583)
grep 0.789 +/- 0.003 (lines: 583)
rg (lines) 0.927 +/- 0.002 (lines: 583)
ag (lines) 4.481 +/- 0.003 (lines: 583)
ucg (lines) 1.774 +/- 0.001 (lines: 583)
pt (lines) 12.939 +/- 0.010 (lines: 583)
sift (lines) 17.184 +/- 0.007 (lines: 583)
grep (lines) 1.300 +/- 0.002 (lines: 583)
subtitles_ru_literal_casei (pattern: Шерлок Холмс)
--------------------------------------------------
rg 1.133 +/- 0.002 (lines: 604)
grep 8.190 +/- 0.005 (lines: 604)
grep (ASCII) 0.784 +/- 0.001 (lines: 583)
rg (lines) 1.733 +/- 0.001 (lines: 604)
ag (lines) (ASCII)* 0.730 +/- 0.001 (lines: 0)*
ucg (lines) (ASCII) 1.775 +/- 0.002 (lines: 583)
subtitles_ru_literal_word (pattern: Шерлок Холмс)
-------------------------------------------------
rg (ASCII)* 0.325 +/- 0.000 (lines: 0)*
ag (ASCII) 0.752 +/- 0.000 (lines: 0)
ucg (ASCII) 1.781 +/- 0.006 (lines: 583)
grep (ASCII) 1.304 +/- 0.003 (lines: 583)
rg 0.929 +/- 0.000 (lines: 579)
grep 1.302 +/- 0.001 (lines: 579)
subtitles_ru_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
----------------------------------------------------------------------------------------
rg 4.904 +/- 0.009 (lines: 41)
rg (ASCII) 3.972 +/- 0.000 (lines: 0)
ag (ASCII)* 2.395 +/- 0.003 (lines: 0)*
ucg (ASCII) 2.895 +/- 0.003 (lines: 0)
grep (ASCII) 2.484 +/- 0.001 (lines: 0)
subtitles_ru_surrounding_words (pattern: \w+\s+Холмс\s+\w+)
-----------------------------------------------------------
rg* 0.956 +/- 0.000 (lines: 278)*
grep 1.662 +/- 0.001 (lines: 278)
ag (ASCII) 2.410 +/- 0.000 (lines: 0)
ucg (ASCII) 2.866 +/- 0.001 (lines: 0)
grep (ASCII) 1.599 +/- 0.002 (lines: 0)

View File

@@ -0,0 +1,93 @@
Ubuntu 16.04 HVM AMI
c3.2xlarge, Xeon E5-2680, 2.8 GHz, 8 CPUs, 16 GB memory, 80 GB SSD
# Generic system setup
mkfs.ext4 /dev/xvdb
sudo mount /dev/xvdb /mnt
sudo chown ubuntu /mnt
sudo apt-get update
sudo apt-get install \ # for building Linux kernel
make gcc bc
sudo apt-get install \ # for the silver searcher
automake pkg-config zlib1g-dev liblzma-dev libpcre3 libpcre3-dev
sudo apt-get install \ # for Universal Code Grep
libtool libpcre2-8-0 libpcre2-dev
sudo apt-get install \ # for sift and the platinum searcher
go
# Get benchmark corpora
cd /mnt
mkdir /mnt/bench
git clone git://github.com/BurntSushi/ripgrep
cd ripgrep/benchsuite
./benchsuite --dir /mnt/bench/ --download all # takes around 15 minutes
# Install search tools
mkdir /mnt/bin/
## ripgrep
cd /mnt
mkdir ripgrep-bin
cd ripgrep-bin
curl -LO 'https://github.com/BurntSushi/ripgrep/releases/download/0.1.2/ripgrep-0.1.2-x86_64-unknown-linux-musl.tar.gz'
cp ripgrep-0.1.2-x86_64-unknown-linux-musl/rg /mnt/bin/
## The Silver Searcher
cd /mnt
git clone git://github.com/ggreer/the_silver_searcher
cd the_silver_searcher
git checkout cda635
./build.sh
cp ag /mnt/bin/
## Universal Code Grep
cd /mnt
git clone git://github.com/gvansickle/ucg
cd ucg
git checkout 487bfb
autoreconf -i
./configure
make
cp ucg /mnt/bin/
## The Platinum Searcher
export GOPATH=/mnt/go
go get github.com/monochromegane/the_platinum_searcher
cd /mnt/go/src/github.com/monochromegane/the_platinum_searcher
git checkout 509368
go install github.com/monochromegane/the_platinum_searcher/cmd/...
cp /mnt/go/bin/pt /mnt/bin/
## Sift
export GOPATH=/mnt/go
go get github.com/svent/sift
cd /mnt/go/src/github.com/svent/sift
git checkout 2d175c
go install
cp /mnt/go/bin/sift /mnt/bin/
## 'git grep' and GNU grep
They are part of the standard Ubuntu install, and are pretty recent (as of
September 2016).
$ git --version
git version 2.7.4
$ grep --version
grep (GNU grep) 2.25
# Running benchmarks
export PATH="/mnt/bin:$PATH"
cd /mnt/ripgrep/benchsuite
./benchsuite \
--dir /mnt/bench/ --raw /mnt/bench/raw.csv --warmup-iter 3 --bench-iter 10
# The above took around 120 minutes to run to completion.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
linux_alternates (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
-------------------------------------------------------------------------
rg (ignore) 0.351 +/- 0.074 (lines: 68)
ag (ignore) 1.747 +/- 0.005 (lines: 68)
git grep (ignore) 0.501 +/- 0.003 (lines: 68)
rg (whitelist)* 0.216 +/- 0.031 (lines: 68)
ucg (whitelist) 0.214 +/- 0.008 (lines: 68)*
linux_alternates_casei (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
-------------------------------------------------------------------------------
rg (ignore) 0.391 +/- 0.078 (lines: 160)
ag (ignore) 1.968 +/- 0.009 (lines: 160)
git grep (ignore) 2.018 +/- 0.006 (lines: 160)
rg (whitelist)* 0.222 +/- 0.001 (lines: 160)*
ucg (whitelist) 0.522 +/- 0.002 (lines: 160)
linux_literal (pattern: PM_RESUME)
----------------------------------
rg (ignore) 0.334 +/- 0.053 (lines: 16)
rg (ignore) (mmap) 1.611 +/- 0.009 (lines: 16)
ag (ignore) (mmap) 1.588 +/- 0.011 (lines: 16)
pt (ignore) 0.456 +/- 0.025 (lines: 16)
sift (ignore) 0.630 +/- 0.004 (lines: 16)
git grep (ignore) 0.345 +/- 0.007 (lines: 16)
rg (whitelist)* 0.228 +/- 0.042 (lines: 16)
ucg (whitelist) 0.218 +/- 0.007 (lines: 16)*
linux_literal_casei (pattern: PM_RESUME)
----------------------------------------
rg (ignore) 0.345 +/- 0.073 (lines: 370)
rg (ignore) (mmap) 1.612 +/- 0.011 (lines: 370)
ag (ignore) (mmap) 1.609 +/- 0.015 (lines: 370)
pt (ignore) 17.204 +/- 0.126 (lines: 370)
sift (ignore) 0.805 +/- 0.005 (lines: 370)
git grep (ignore) 0.343 +/- 0.007 (lines: 370)
rg (whitelist)* 0.222 +/- 0.021 (lines: 370)
ucg (whitelist) 0.217 +/- 0.006 (lines: 370)*
linux_literal_default (pattern: PM_RESUME)
------------------------------------------
rg 0.349 +/- 0.104 (lines: 16)
ag 1.589 +/- 0.009 (lines: 16)
ucg* 0.218 +/- 0.007 (lines: 16)*
pt 0.462 +/- 0.012 (lines: 16)
sift 0.352 +/- 0.018 (lines: 16)
git grep 0.342 +/- 0.005 (lines: 16)
linux_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
-----------------------------------------------------------------
rg (ignore) 0.577 +/- 0.003 (lines: 490)
rg (ignore) (ASCII) 0.416 +/- 0.025 (lines: 490)
ag (ignore) (ASCII) 2.339 +/- 0.010 (lines: 766)
pt (ignore) (ASCII) 22.066 +/- 0.057 (lines: 490)
sift (ignore) (ASCII) 25.563 +/- 0.108 (lines: 490)
git grep (ignore) 26.382 +/- 0.044 (lines: 490)
git grep (ignore) (ASCII) 4.153 +/- 0.010 (lines: 490)
rg (whitelist) 0.503 +/- 0.011 (lines: 419)
rg (whitelist) (ASCII)* 0.343 +/- 0.038 (lines: 419)*
ucg (whitelist) (ASCII) 1.130 +/- 0.003 (lines: 416)
linux_re_literal_suffix (pattern: [A-Z]+_RESUME)
------------------------------------------------
rg (ignore) 0.318 +/- 0.034 (lines: 1652)
ag (ignore) 1.899 +/- 0.008 (lines: 1652)
pt (ignore) 13.713 +/- 0.241 (lines: 1652)
sift (ignore) 10.172 +/- 0.186 (lines: 1652)
git grep (ignore) 1.108 +/- 0.004 (lines: 1652)
rg (whitelist)* 0.221 +/- 0.022 (lines: 1630)*
ucg (whitelist) 0.301 +/- 0.001 (lines: 1630)
linux_unicode_greek (pattern: \p{Greek})
----------------------------------------
rg* 0.414 +/- 0.021 (lines: 23)*
pt 12.745 +/- 0.166 (lines: 23)
sift 7.767 +/- 0.264 (lines: 23)
linux_unicode_greek_casei (pattern: \p{Greek})
----------------------------------------------
rg 0.425 +/- 0.027 (lines: 103)
pt 12.612 +/- 0.217 (lines: 23)
sift* 0.002 +/- 0.000 (lines: 0)*
linux_unicode_word (pattern: \wAh)
----------------------------------
rg (ignore) 0.355 +/- 0.073 (lines: 186)
rg (ignore) (ASCII) 0.329 +/- 0.060 (lines: 174)
ag (ignore) (ASCII) 1.774 +/- 0.011 (lines: 174)
pt (ignore) (ASCII) 14.180 +/- 0.180 (lines: 174)
sift (ignore) (ASCII) 11.087 +/- 0.108 (lines: 174)
git grep (ignore) 13.045 +/- 0.008 (lines: 186)
git grep (ignore) (ASCII) 2.991 +/- 0.004 (lines: 174)
rg (whitelist) 0.235 +/- 0.031 (lines: 180)
rg (whitelist) (ASCII)* 0.225 +/- 0.023 (lines: 168)*
ucg (ASCII) 0.229 +/- 0.007 (lines: 168)
linux_word (pattern: PM_RESUME)
-------------------------------
rg (ignore) 0.362 +/- 0.080 (lines: 6)
ag (ignore) 1.603 +/- 0.009 (lines: 6)
pt (ignore) 14.417 +/- 0.144 (lines: 6)
sift (ignore) 7.840 +/- 0.123 (lines: 6)
git grep (ignore) 0.341 +/- 0.005 (lines: 6)
rg (whitelist)* 0.220 +/- 0.026 (lines: 6)*
ucg (whitelist) 0.221 +/- 0.007 (lines: 6)
subtitles_en_alternate (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
---------------------------------------------------------------------------------------------------------------
rg (lines) 0.619 +/- 0.001 (lines: 848)
ag (lines) 3.757 +/- 0.001 (lines: 848)
ucg (lines) 1.479 +/- 0.002 (lines: 848)
grep (lines) 3.412 +/- 0.004 (lines: 848)
rg* 0.294 +/- 0.001 (lines: 848)*
grep 2.955 +/- 0.003 (lines: 848)
subtitles_en_alternate_casei (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
---------------------------------------------------------------------------------------------------------------------
ag (ASCII) 5.170 +/- 0.004 (lines: 862)
ucg (ASCII) 3.453 +/- 0.005 (lines: 862)
grep (ASCII) 4.537 +/- 0.025 (lines: 862)
rg* 2.724 +/- 0.002 (lines: 862)*
grep 5.125 +/- 0.006 (lines: 862)
subtitles_en_literal (pattern: Sherlock Holmes)
-----------------------------------------------
rg* 0.268 +/- 0.000 (lines: 629)*
rg (no mmap) 0.336 +/- 0.001 (lines: 629)
pt 3.433 +/- 0.002 (lines: 629)
sift 0.326 +/- 0.002 (lines: 629)
grep 0.516 +/- 0.001 (lines: 629)
rg (lines) 0.595 +/- 0.001 (lines: 629)
ag (lines) 2.730 +/- 0.003 (lines: 629)
ucg (lines) 0.745 +/- 0.001 (lines: 629)
pt (lines) 3.434 +/- 0.005 (lines: 629)
sift (lines) 0.756 +/- 0.002 (lines: 629)
grep (lines) 0.969 +/- 0.001 (lines: 629)
subtitles_en_literal_casei (pattern: Sherlock Holmes)
-----------------------------------------------------
rg* 0.366 +/- 0.001 (lines: 642)*
grep 4.084 +/- 0.005 (lines: 642)
grep (ASCII) 0.614 +/- 0.001 (lines: 642)
rg (lines) 0.696 +/- 0.002 (lines: 642)
ag (lines) (ASCII) 2.775 +/- 0.004 (lines: 642)
ucg (lines) (ASCII) 0.841 +/- 0.002 (lines: 642)
subtitles_en_literal_word (pattern: Sherlock Holmes)
----------------------------------------------------
rg (ASCII) 0.596 +/- 0.001 (lines: 629)
ag (ASCII) 2.729 +/- 0.001 (lines: 629)
ucg (ASCII) 0.810 +/- 0.002 (lines: 629)
grep (ASCII) 0.970 +/- 0.000 (lines: 629)
rg* 0.596 +/- 0.001 (lines: 629)*
grep 0.972 +/- 0.003 (lines: 629)
subtitles_en_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
----------------------------------------------------------------------------------------
rg 2.777 +/- 0.003 (lines: 13)
rg (ASCII)* 2.541 +/- 0.005 (lines: 13)*
ag (ASCII) 10.076 +/- 0.005 (lines: 48)
ucg (ASCII) 7.771 +/- 0.004 (lines: 13)
grep (ASCII) 4.411 +/- 0.004 (lines: 13)
subtitles_en_surrounding_words (pattern: \w+\s+Holmes\s+\w+)
------------------------------------------------------------
rg 0.605 +/- 0.000 (lines: 317)
grep 1.286 +/- 0.002 (lines: 317)
rg (ASCII)* 0.602 +/- 0.000 (lines: 317)*
ag (ASCII) 11.663 +/- 0.008 (lines: 323)
ucg (ASCII) 4.690 +/- 0.002 (lines: 317)
grep (ASCII) 1.276 +/- 0.002 (lines: 317)
subtitles_ru_alternate (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
-----------------------------------------------------------------------------------------------------------
rg (lines) 1.902 +/- 0.002 (lines: 691)
ag (lines) 5.892 +/- 0.003 (lines: 691)
ucg (lines) 2.864 +/- 0.006 (lines: 691)
grep (lines) 8.511 +/- 0.005 (lines: 691)
rg* 1.300 +/- 0.002 (lines: 691)*
grep 7.994 +/- 0.017 (lines: 691)
subtitles_ru_alternate_casei (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
-----------------------------------------------------------------------------------------------------------------
ag (ASCII) 5.891 +/- 0.001 (lines: 691)
ucg (ASCII)* 2.868 +/- 0.005 (lines: 691)*
grep (ASCII) 8.572 +/- 0.009 (lines: 691)
rg 4.834 +/- 0.004 (lines: 735)
grep 8.729 +/- 0.004 (lines: 735)
subtitles_ru_literal (pattern: Шерлок Холмс)
--------------------------------------------
rg* 0.325 +/- 0.001 (lines: 583)*
rg (no mmap) 0.452 +/- 0.002 (lines: 583)
pt 12.917 +/- 0.009 (lines: 583)
sift 16.418 +/- 0.008 (lines: 583)
grep 0.780 +/- 0.001 (lines: 583)
rg (lines) 0.926 +/- 0.001 (lines: 583)
ag (lines) 4.481 +/- 0.003 (lines: 583)
ucg (lines) 1.889 +/- 0.004 (lines: 583)
pt (lines) 12.935 +/- 0.011 (lines: 583)
sift (lines) 17.177 +/- 0.010 (lines: 583)
grep (lines) 1.300 +/- 0.003 (lines: 583)
subtitles_ru_literal_casei (pattern: Шерлок Холмс)
--------------------------------------------------
rg 1.131 +/- 0.001 (lines: 604)
grep 8.187 +/- 0.006 (lines: 604)
grep (ASCII) 0.785 +/- 0.001 (lines: 583)
rg (lines) 1.733 +/- 0.002 (lines: 604)
ag (lines) (ASCII)* 0.729 +/- 0.001 (lines: 0)*
ucg (lines) (ASCII) 1.896 +/- 0.005 (lines: 583)
subtitles_ru_literal_word (pattern: Шерлок Холмс)
-------------------------------------------------
rg (ASCII)* 0.325 +/- 0.000 (lines: 0)*
ag (ASCII) 0.753 +/- 0.001 (lines: 0)
ucg (ASCII) 1.891 +/- 0.004 (lines: 583)
grep (ASCII) 1.303 +/- 0.004 (lines: 583)
rg 0.929 +/- 0.001 (lines: 579)
grep 1.304 +/- 0.003 (lines: 579)
subtitles_ru_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
----------------------------------------------------------------------------------------
rg 4.905 +/- 0.003 (lines: 41)
rg (ASCII) 3.973 +/- 0.002 (lines: 0)
ag (ASCII)* 2.395 +/- 0.004 (lines: 0)*
ucg (ASCII) 3.006 +/- 0.005 (lines: 0)
grep (ASCII) 2.483 +/- 0.005 (lines: 0)
subtitles_ru_surrounding_words (pattern: \w+\s+Холмс\s+\w+)
-----------------------------------------------------------
rg* 0.957 +/- 0.001 (lines: 278)*
grep 1.660 +/- 0.002 (lines: 278)
ag (ASCII) 2.411 +/- 0.001 (lines: 0)
ucg (ASCII) 2.980 +/- 0.002 (lines: 0)
grep (ASCII) 1.596 +/- 0.003 (lines: 0)

View File

@@ -0,0 +1,484 @@
benchmark,warmup_iter,iter,name,command,duration,lines,env
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.16187143325805664,68,
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.15862464904785156,68,
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.15711188316345215,68,
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5682125091552734,68,
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.551994800567627,68,
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5516140460968018,68,
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.24930572509765625,68,LC_ALL=C
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.25743985176086426,68,LC_ALL=C
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.24960589408874512,68,LC_ALL=C
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.1039431095123291,68,
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.10251975059509277,68,
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.10156440734863281,68,
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.15678954124450684,68,
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.15236687660217285,68,
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.1554563045501709,68,
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.16192197799682617,160,
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.15988397598266602,160,
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.1610555648803711,160,
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6026794910430908,160,
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6083211898803711,160,
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.674222469329834,160,
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.0635485649108887,160,LC_ALL=C
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.8944556713104248,160,LC_ALL=C
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.860692024230957,160,LC_ALL=C
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.11778616905212402,160,
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.11570453643798828,160,
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.13424015045166016,160,
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.2392585277557373,160,
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.2421557903289795,160,
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.2390902042388916,160,
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.14362168312072754,16,
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.16165685653686523,16,
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.1725757122039795,16,
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,0.3785591125488281,16,
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,0.3961794376373291,16,
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,0.3924229145050049,16,
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,0.5462315082550049,16,
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,0.7240490913391113,16,
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,0.4528837203979492,16,
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.16354584693908691,16,
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.15301966667175293,16,
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.15467524528503418,16,
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.33901119232177734,16,
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.34641242027282715,16,
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.3532230854034424,16,
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.1970062255859375,16,LC_ALL=C
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.21334624290466309,16,LC_ALL=C
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.19323515892028809,16,LC_ALL=C
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.10708379745483398,16,
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.10089921951293945,16,
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.10404157638549805,16,
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.17191362380981445,16,
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.1670548915863037,16,
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.16875147819519043,16,
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.16549420356750488,370,
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.14867877960205078,370,
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.1509239673614502,370,
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,0.38896727561950684,370,
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,0.39926719665527344,370,
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,0.3912012577056885,370,
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,0.48294734954833984,370,
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,0.4827127456665039,370,
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,0.4216601848602295,370,
linux_literal_casei,1,3,pt (ignore),pt -i PM_RESUME,11.884198665618896,370,
linux_literal_casei,1,3,pt (ignore),pt -i PM_RESUME,12.05774974822998,370,
linux_literal_casei,1,3,pt (ignore),pt -i PM_RESUME,11.864668130874634,370,
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.3698842525482178,370,
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.3745250701904297,370,
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.3670051097869873,370,
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.18896126747131348,370,LC_ALL=C
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.19655537605285645,370,LC_ALL=C
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.183945894241333,370,LC_ALL=C
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.11336517333984375,370,
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.10497522354125977,370,
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.10771870613098145,370,
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.1626441478729248,370,
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.16270971298217773,370,
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.1596980094909668,370,
linux_literal_default,1,3,rg,rg PM_RESUME,0.14002084732055664,16,
linux_literal_default,1,3,rg,rg PM_RESUME,0.13782882690429688,16,
linux_literal_default,1,3,rg,rg PM_RESUME,0.13794231414794922,16,
linux_literal_default,1,3,ag,ag PM_RESUME,0.4623262882232666,16,
linux_literal_default,1,3,ag,ag PM_RESUME,0.419907808303833,16,
linux_literal_default,1,3,ag,ag PM_RESUME,0.44193005561828613,16,
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.1634502410888672,16,
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.17029428482055664,16,
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.16076922416687012,16,
linux_literal_default,1,3,pt,pt PM_RESUME,0.15809178352355957,16,
linux_literal_default,1,3,pt,pt PM_RESUME,0.1554114818572998,16,
linux_literal_default,1,3,pt,pt PM_RESUME,0.15415430068969727,16,
linux_literal_default,1,3,sift,sift PM_RESUME,0.1160738468170166,16,
linux_literal_default,1,3,sift,sift PM_RESUME,0.11754369735717773,16,
linux_literal_default,1,3,sift,sift PM_RESUME,0.11825299263000488,16,
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.18619132041931152,16,LC_ALL=en_US.UTF-8
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.16708111763000488,16,LC_ALL=en_US.UTF-8
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.20236515998840332,16,LC_ALL=en_US.UTF-8
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.34000611305236816,490,
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.36969494819641113,490,
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3622872829437256,490,
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2572669982910156,490,
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3148176670074463,490,
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3092081546783447,490,
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.7651598453521729,766,
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.7487096786499023,766,
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.7506840229034424,766,
linux_no_literal,1,3,pt (ignore) (ASCII),pt -e \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},12.426137685775757,490,
linux_no_literal,1,3,pt (ignore) (ASCII),pt -e \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},12.454124450683594,490,
linux_no_literal,1,3,pt (ignore) (ASCII),pt -e \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},12.573740243911743,490,
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},8.734328746795654,490,
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},8.95349931716919,490,
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},8.97816801071167,490,
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},8.792009830474854,490,LC_ALL=en_US.UTF-8
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},8.744960308074951,490,LC_ALL=en_US.UTF-8
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},9.04098892211914,490,LC_ALL=en_US.UTF-8
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.8596012592315674,490,LC_ALL=C
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.824751853942871,490,LC_ALL=C
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.9543235301971436,490,LC_ALL=C
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.31849026679992676,419,
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3028290271759033,419,
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.31795716285705566,419,
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.22214102745056152,419,
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2748534679412842,419,
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2098088264465332,419,
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4494349956512451,416,
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.44551706314086914,416,
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4425935745239258,416,
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.19018173217773438,1652,
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.1422746181488037,1652,
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.14041566848754883,1652,
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,0.5190994739532471,1652,
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,0.5290501117706299,1652,
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,0.5360753536224365,1652,
linux_re_literal_suffix,1,3,pt (ignore),pt -e [A-Z]+_RESUME,11.900719404220581,1652,
linux_re_literal_suffix,1,3,pt (ignore),pt -e [A-Z]+_RESUME,11.905181646347046,1652,
linux_re_literal_suffix,1,3,pt (ignore),pt -e [A-Z]+_RESUME,11.878832817077637,1652,
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,3.9338936805725098,1652,
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,3.971776247024536,1652,
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,4.010965585708618,1652,
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,0.553400993347168,1652,LC_ALL=C
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,0.5757920742034912,1652,LC_ALL=C
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,0.6472165584564209,1652,LC_ALL=C
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.10109567642211914,1630,
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.1010751724243164,1630,
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.10259413719177246,1630,
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.13558602333068848,1630,
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.13765740394592285,1630,
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.14018011093139648,1630,
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.2655603885650635,23,
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.2579922676086426,23,
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.2389824390411377,23,
linux_unicode_greek,1,3,pt,pt -e \p{Greek},11.789764881134033,23,
linux_unicode_greek,1,3,pt,pt -e \p{Greek},11.717109680175781,23,
linux_unicode_greek,1,3,pt,pt -e \p{Greek},11.714937448501587,23,
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},2.732529401779175,23,
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},2.782707452774048,23,
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},2.8073642253875732,23,
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.29653406143188477,103,
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.24062681198120117,103,
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.24714946746826172,103,
linux_unicode_greek_casei,1,3,pt,pt -i -e \p{Greek},11.754312515258789,23,
linux_unicode_greek_casei,1,3,pt,pt -i -e \p{Greek},11.742995500564575,23,
linux_unicode_greek_casei,1,3,pt,pt -i -e \p{Greek},11.763852596282959,23,
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.0018308162689208984,,
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.0017769336700439453,,
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.0018434524536132812,,
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.19392776489257812,186,
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.14665579795837402,186,
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.15625548362731934,186,
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.14500045776367188,174,
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.15199685096740723,174,
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.14606475830078125,174,
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,0.47933006286621094,174,
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,0.4965095520019531,174,
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,0.4971892833709717,174,
linux_unicode_word,1,3,pt (ignore) (ASCII),pt -e \wAh,12.043948650360107,174,
linux_unicode_word,1,3,pt (ignore) (ASCII),pt -e \wAh,12.024799823760986,174,
linux_unicode_word,1,3,pt (ignore) (ASCII),pt -e \wAh,12.032919883728027,174,
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \wAh,4.146677255630493,174,
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \wAh,4.05977988243103,174,
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \wAh,4.246629238128662,174,
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,4.401025772094727,186,LC_ALL=en_US.UTF-8
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,4.499484062194824,186,LC_ALL=en_US.UTF-8
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,4.530885934829712,186,LC_ALL=en_US.UTF-8
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,1.552142858505249,174,LC_ALL=C
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,1.4553732872009277,174,LC_ALL=C
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,1.3407535552978516,174,LC_ALL=C
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.10183477401733398,180,
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.10535907745361328,180,
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.10527634620666504,180,
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.10268187522888184,168,
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.10159945487976074,168,
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.09854245185852051,168,
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.17232871055603027,168,
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.17245817184448242,168,
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.1736738681793213,168,
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.18302679061889648,6,
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.14654874801635742,6,
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.14666008949279785,6,
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,0.43340468406677246,6,
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,0.4431777000427246,6,
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,0.4939415454864502,6,
linux_word,1,3,pt (ignore),pt -w PM_RESUME,12.12212347984314,6,
linux_word,1,3,pt (ignore),pt -w PM_RESUME,12.106850862503052,6,
linux_word,1,3,pt (ignore),pt -w PM_RESUME,12.119231224060059,6,
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,3.3320345878601074,6,
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,3.2089524269104004,6,
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,3.34165096282959,6,
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.20112895965576172,6,LC_ALL=C
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.16607999801635742,6,LC_ALL=C
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.2049086093902588,6,LC_ALL=C
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.10440325736999512,6,
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.09853243827819824,6,
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.09580087661743164,6,
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.16874432563781738,6,
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.16241073608398438,6,
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.1621534824371338,6,
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5109667778015137,848,
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.662921667098999,848,
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.627272367477417,848,
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.4915170669555664,848,
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.294611930847168,848,
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.475243330001831,848,
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.450028419494629,848,
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.266982078552246,848,
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.429199457168579,848,
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.81933856010437,848,LC_ALL=C
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.829207420349121,848,LC_ALL=C
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.795469284057617,848,LC_ALL=C
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.3135373592376709,848,
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.47072267532348633,848,
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.3777759075164795,848,
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.2277214527130127,848,LC_ALL=C
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.4641876220703125,848,LC_ALL=C
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.4201643466949463,848,LC_ALL=C
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.925377368927002,862,
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.7743782997131348,862,
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.9031031131744385,862,
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.902085542678833,862,
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.9104111194610596,862,
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.9407846927642822,862,
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.6935694217681885,862,LC_ALL=C
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.7745134830474854,862,LC_ALL=C
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.5532472133636475,862,LC_ALL=C
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.3000056743621826,862,
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.46085786819458,862,
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.2774720191955566,862,
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,4.183770418167114,862,LC_ALL=en_US.UTF-8
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,4.210017442703247,862,LC_ALL=en_US.UTF-8
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,4.052750587463379,862,LC_ALL=en_US.UTF-8
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.2422008514404297,629,
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.18678736686706543,629,
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.20187044143676758,629,
subtitles_en_literal,1,3,rg (no mmap),rg --no-mmap Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.21189618110656738,629,
subtitles_en_literal,1,3,rg (no mmap),rg --no-mmap Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.21378588676452637,629,
subtitles_en_literal,1,3,rg (no mmap),rg --no-mmap Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.2638204097747803,629,
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.6680185794830322,629,
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.7018795013427734,629,
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.7135086059570312,629,
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.33170270919799805,629,
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.3204488754272461,629,
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.3302597999572754,629,
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5119576454162598,629,LC_ALL=C
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.48076844215393066,629,LC_ALL=C
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.6118988990783691,629,LC_ALL=C
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.6149063110351562,629,
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.547245979309082,629,
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5441193580627441,629,
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.990401268005371,629,
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.9924650192260742,629,
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.807952642440796,629,
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.772294282913208,629,
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.8758792877197266,629,
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.8043625354766846,629,
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.5409111976623535,629,
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.535851001739502,629,
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.6951041221618652,629,
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.7138817310333252,629,
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.727524995803833,629,
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.7202486991882324,629,
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.0228428840637207,629,LC_ALL=C
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.9452800750732422,629,LC_ALL=C
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.0286569595336914,629,LC_ALL=C
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.36867737770080566,642,
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.391110897064209,642,
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.42432594299316406,642,
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.2124955654144287,642,LC_ALL=en_US.UTF-8
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.288994789123535,642,LC_ALL=en_US.UTF-8
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.2279436588287354,642,LC_ALL=en_US.UTF-8
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5713660717010498,642,LC_ALL=C
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5478014945983887,642,LC_ALL=C
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5502541065216064,642,LC_ALL=C
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5866222381591797,642,
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5829083919525146,642,
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.7458250522613525,642,
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.8324756622314453,642,
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.8361680507659912,642,
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.017822265625,642,
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.9228289127349854,642,
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.9356215000152588,642,
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.9355306625366211,642,
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.46090102195739746,629,
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.41375064849853516,629,
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.4181649684906006,629,
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.8445067405700684,629,
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.805356740951538,629,
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.8274097442626953,629,
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.9036450386047363,629,
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.7601873874664307,629,
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.7341368198394775,629,
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.867140531539917,629,LC_ALL=C
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.8452246189117432,629,LC_ALL=C
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.8254234790802002,629,LC_ALL=C
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.39222264289855957,629,
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5510556697845459,629,
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.439284086227417,629,
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.8688523769378662,629,LC_ALL=en_US.UTF-8
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.0727341175079346,629,LC_ALL=en_US.UTF-8
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.8665497303009033,629,LC_ALL=en_US.UTF-8
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.2950611114501953,13,
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.226304769515991,13,
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.3140387535095215,13,
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.055910587310791,13,
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.032794952392578,13,
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.0602478981018066,13,
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,7.566168308258057,48,
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,7.360717535018921,48,
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,7.30781364440918,48,
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,6.13957142829895,13,
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,6.132368564605713,13,
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,5.929611921310425,13,
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.432003974914551,13,LC_ALL=C
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.714038610458374,13,LC_ALL=C
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.6915385723114014,13,LC_ALL=C
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.42601513862609863,317,
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.561565637588501,317,
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5141217708587646,317,
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.3077969551086426,317,LC_ALL=en_US.UTF-8
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.1768431663513184,317,LC_ALL=en_US.UTF-8
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.0883615016937256,317,LC_ALL=en_US.UTF-8
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5061089992523193,317,
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.4004178047180176,317,
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5536422729492188,317,
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,4.981522798538208,323,
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,4.83101487159729,323,
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,5.025806427001953,323,
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.906707286834717,317,
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.8826284408569336,317,
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,3.852736711502075,317,
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.262470006942749,317,LC_ALL=C
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.1661438941955566,317,LC_ALL=C
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.1648437976837158,317,LC_ALL=C
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.79972243309021,691,
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.629694938659668,691,
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.8325402736663818,691,
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.124853849411011,691,
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.0995543003082275,691,
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.105457544326782,691,
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.491947650909424,691,
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.544341802597046,691,
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.6295418739318848,691,
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.948693513870239,691,LC_ALL=C
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.991183280944824,691,LC_ALL=C
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,7.004202842712402,691,LC_ALL=C
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.1708271503448486,691,
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3341143131256104,691,
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3589985370635986,691,
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.3860955238342285,691,LC_ALL=C
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.437295436859131,691,LC_ALL=C
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.34372615814209,691,LC_ALL=C
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.100299119949341,691,
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.343926668167114,691,
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.247299432754517,691,
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.6179757118225098,691,
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.438668727874756,691,
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.6296229362487793,691,
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.816138744354248,691,LC_ALL=C
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,7.005900859832764,691,LC_ALL=C
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.96263861656189,691,LC_ALL=C
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.222437858581543,735,
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.260664463043213,735,
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.040424823760986,735,
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,7.112156391143799,735,LC_ALL=en_US.UTF-8
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,7.066831350326538,735,LC_ALL=en_US.UTF-8
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.983258962631226,735,LC_ALL=en_US.UTF-8
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.3009657859802246,583,
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.31114768981933594,583,
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.3145453929901123,583,
subtitles_ru_literal,1,3,rg (no mmap),rg --no-mmap Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.3670217990875244,583,
subtitles_ru_literal,1,3,rg (no mmap),rg --no-mmap Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.39557576179504395,583,
subtitles_ru_literal,1,3,rg (no mmap),rg --no-mmap Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.38857460021972656,583,
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.653504133224487,583,
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.440903663635254,583,
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.604345321655273,583,
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.333267450332642,583,
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.3738181591033936,583,
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.604928970336914,583,
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.7382421493530273,583,LC_ALL=C
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.7205381393432617,583,LC_ALL=C
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8509528636932373,583,LC_ALL=C
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.6589868068695068,583,
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.857933759689331,583,
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.7283596992492676,583,
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.111611843109131,583,
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.1084604263305664,583,
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.993370771408081,583,
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.8463020324707031,583,
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.8160367012023926,583,
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.9012954235076904,583,
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.590208530426025,583,
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.712487697601318,583,
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.628024339675903,583,
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.999194145202637,583,
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.639494895935059,583,
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.6554951667785645,583,
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3319404125213623,583,LC_ALL=C
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3712143898010254,583,LC_ALL=C
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.2382845878601074,583,LC_ALL=C
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.2365717887878418,604,
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.2306108474731445,604,
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.22041654586792,604,
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.636392116546631,604,LC_ALL=en_US.UTF-8
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.447664976119995,604,LC_ALL=en_US.UTF-8
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.47466516494751,604,LC_ALL=en_US.UTF-8
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8679373264312744,583,LC_ALL=C
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8400778770446777,583,LC_ALL=C
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8912734985351562,583,LC_ALL=C
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.6649067401885986,604,
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.472435712814331,604,
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5518934726715088,604,
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.6329071521759033,,
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.6236186027526855,,
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.744124174118042,,
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.842088222503662,583,
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.6797516345977783,583,
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.86281418800354,583,
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.3059053421020508,,
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.3220036029815674,,
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.3317573070526123,,
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.790125846862793,,
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8004007339477539,,
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.7884745597839355,,
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.8595643043518066,583,
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.8338594436645508,583,
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.6697683334350586,583,
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.1608448028564453,583,LC_ALL=C
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3229436874389648,583,LC_ALL=C
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3650012016296387,583,LC_ALL=C
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.840968132019043,579,
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.7012484073638916,579,
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.6782803535461426,579,
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3308250904083252,579,LC_ALL=en_US.UTF-8
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.2687301635742188,579,LC_ALL=en_US.UTF-8
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.317870855331421,579,LC_ALL=en_US.UTF-8
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.8553390502929688,41,
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.6567201614379883,41,
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.6484830379486084,41,
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.968876838684082,,
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.0976366996765137,,
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.9159646034240723,,
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.8425374031066895,,
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.0483176708221436,,
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.0838112831115723,,
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.510307550430298,,
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.542471408843994,,
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.5069386959075928,,
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.0888967514038086,,LC_ALL=C
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.119218349456787,,LC_ALL=C
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.0531933307647705,,LC_ALL=C
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.792813777923584,278,
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8660504817962646,278,
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8515620231628418,278,
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.4405500888824463,278,LC_ALL=en_US.UTF-8
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.6386635303497314,278,LC_ALL=en_US.UTF-8
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5895426273345947,278,LC_ALL=en_US.UTF-8
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.032708168029785,,
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.927478551864624,,
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.019101619720459,,
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.6226632595062256,,
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.5062124729156494,,
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.5160763263702393,,
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.613976240158081,,LC_ALL=C
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5636706352233887,,LC_ALL=C
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.4378304481506348,,LC_ALL=C
1 benchmark warmup_iter iter name command duration lines env
2 linux_alternates 1 3 rg (ignore) rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.16187143325805664 68
3 linux_alternates 1 3 rg (ignore) rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.15862464904785156 68
4 linux_alternates 1 3 rg (ignore) rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.15711188316345215 68
5 linux_alternates 1 3 ag (ignore) ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.5682125091552734 68
6 linux_alternates 1 3 ag (ignore) ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.551994800567627 68
7 linux_alternates 1 3 ag (ignore) ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.5516140460968018 68
8 linux_alternates 1 3 git grep (ignore) git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.24930572509765625 68 LC_ALL=C
9 linux_alternates 1 3 git grep (ignore) git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.25743985176086426 68 LC_ALL=C
10 linux_alternates 1 3 git grep (ignore) git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.24960589408874512 68 LC_ALL=C
11 linux_alternates 1 3 rg (whitelist) rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.1039431095123291 68
12 linux_alternates 1 3 rg (whitelist) rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.10251975059509277 68
13 linux_alternates 1 3 rg (whitelist) rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.10156440734863281 68
14 linux_alternates 1 3 ucg (whitelist) ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.15678954124450684 68
15 linux_alternates 1 3 ucg (whitelist) ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.15236687660217285 68
16 linux_alternates 1 3 ucg (whitelist) ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.1554563045501709 68
17 linux_alternates_casei 1 3 rg (ignore) rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.16192197799682617 160
18 linux_alternates_casei 1 3 rg (ignore) rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.15988397598266602 160
19 linux_alternates_casei 1 3 rg (ignore) rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.1610555648803711 160
20 linux_alternates_casei 1 3 ag (ignore) ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.6026794910430908 160
21 linux_alternates_casei 1 3 ag (ignore) ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.6083211898803711 160
22 linux_alternates_casei 1 3 ag (ignore) ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.674222469329834 160
23 linux_alternates_casei 1 3 git grep (ignore) git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 1.0635485649108887 160 LC_ALL=C
24 linux_alternates_casei 1 3 git grep (ignore) git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.8944556713104248 160 LC_ALL=C
25 linux_alternates_casei 1 3 git grep (ignore) git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.860692024230957 160 LC_ALL=C
26 linux_alternates_casei 1 3 rg (whitelist) rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.11778616905212402 160
27 linux_alternates_casei 1 3 rg (whitelist) rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.11570453643798828 160
28 linux_alternates_casei 1 3 rg (whitelist) rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.13424015045166016 160
29 linux_alternates_casei 1 3 ucg (whitelist) ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.2392585277557373 160
30 linux_alternates_casei 1 3 ucg (whitelist) ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.2421557903289795 160
31 linux_alternates_casei 1 3 ucg (whitelist) ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT 0.2390902042388916 160
32 linux_literal 1 3 rg (ignore) rg -n PM_RESUME 0.14362168312072754 16
33 linux_literal 1 3 rg (ignore) rg -n PM_RESUME 0.16165685653686523 16
34 linux_literal 1 3 rg (ignore) rg -n PM_RESUME 0.1725757122039795 16
35 linux_literal 1 3 rg (ignore) (mmap) rg -n --mmap PM_RESUME 0.3785591125488281 16
36 linux_literal 1 3 rg (ignore) (mmap) rg -n --mmap PM_RESUME 0.3961794376373291 16
37 linux_literal 1 3 rg (ignore) (mmap) rg -n --mmap PM_RESUME 0.3924229145050049 16
38 linux_literal 1 3 ag (ignore) (mmap) ag -s PM_RESUME 0.5462315082550049 16
39 linux_literal 1 3 ag (ignore) (mmap) ag -s PM_RESUME 0.7240490913391113 16
40 linux_literal 1 3 ag (ignore) (mmap) ag -s PM_RESUME 0.4528837203979492 16
41 linux_literal 1 3 pt (ignore) pt PM_RESUME 0.16354584693908691 16
42 linux_literal 1 3 pt (ignore) pt PM_RESUME 0.15301966667175293 16
43 linux_literal 1 3 pt (ignore) pt PM_RESUME 0.15467524528503418 16
44 linux_literal 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME 0.33901119232177734 16
45 linux_literal 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME 0.34641242027282715 16
46 linux_literal 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME 0.3532230854034424 16
47 linux_literal 1 3 git grep (ignore) git grep -I -n PM_RESUME 0.1970062255859375 16 LC_ALL=C
48 linux_literal 1 3 git grep (ignore) git grep -I -n PM_RESUME 0.21334624290466309 16 LC_ALL=C
49 linux_literal 1 3 git grep (ignore) git grep -I -n PM_RESUME 0.19323515892028809 16 LC_ALL=C
50 linux_literal 1 3 rg (whitelist) rg -n --no-ignore -tall PM_RESUME 0.10708379745483398 16
51 linux_literal 1 3 rg (whitelist) rg -n --no-ignore -tall PM_RESUME 0.10089921951293945 16
52 linux_literal 1 3 rg (whitelist) rg -n --no-ignore -tall PM_RESUME 0.10404157638549805 16
53 linux_literal 1 3 ucg (whitelist) ucg --nosmart-case PM_RESUME 0.17191362380981445 16
54 linux_literal 1 3 ucg (whitelist) ucg --nosmart-case PM_RESUME 0.1670548915863037 16
55 linux_literal 1 3 ucg (whitelist) ucg --nosmart-case PM_RESUME 0.16875147819519043 16
56 linux_literal_casei 1 3 rg (ignore) rg -n -i PM_RESUME 0.16549420356750488 370
57 linux_literal_casei 1 3 rg (ignore) rg -n -i PM_RESUME 0.14867877960205078 370
58 linux_literal_casei 1 3 rg (ignore) rg -n -i PM_RESUME 0.1509239673614502 370
59 linux_literal_casei 1 3 rg (ignore) (mmap) rg -n -i --mmap PM_RESUME 0.38896727561950684 370
60 linux_literal_casei 1 3 rg (ignore) (mmap) rg -n -i --mmap PM_RESUME 0.39926719665527344 370
61 linux_literal_casei 1 3 rg (ignore) (mmap) rg -n -i --mmap PM_RESUME 0.3912012577056885 370
62 linux_literal_casei 1 3 ag (ignore) (mmap) ag -i PM_RESUME 0.48294734954833984 370
63 linux_literal_casei 1 3 ag (ignore) (mmap) ag -i PM_RESUME 0.4827127456665039 370
64 linux_literal_casei 1 3 ag (ignore) (mmap) ag -i PM_RESUME 0.4216601848602295 370
65 linux_literal_casei 1 3 pt (ignore) pt -i PM_RESUME 11.884198665618896 370
66 linux_literal_casei 1 3 pt (ignore) pt -i PM_RESUME 12.05774974822998 370
67 linux_literal_casei 1 3 pt (ignore) pt -i PM_RESUME 11.864668130874634 370
68 linux_literal_casei 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME 0.3698842525482178 370
69 linux_literal_casei 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME 0.3745250701904297 370
70 linux_literal_casei 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME 0.3670051097869873 370
71 linux_literal_casei 1 3 git grep (ignore) git grep -I -n -i PM_RESUME 0.18896126747131348 370 LC_ALL=C
72 linux_literal_casei 1 3 git grep (ignore) git grep -I -n -i PM_RESUME 0.19655537605285645 370 LC_ALL=C
73 linux_literal_casei 1 3 git grep (ignore) git grep -I -n -i PM_RESUME 0.183945894241333 370 LC_ALL=C
74 linux_literal_casei 1 3 rg (whitelist) rg -n -i --no-ignore -tall PM_RESUME 0.11336517333984375 370
75 linux_literal_casei 1 3 rg (whitelist) rg -n -i --no-ignore -tall PM_RESUME 0.10497522354125977 370
76 linux_literal_casei 1 3 rg (whitelist) rg -n -i --no-ignore -tall PM_RESUME 0.10771870613098145 370
77 linux_literal_casei 1 3 ucg (whitelist) ucg -i PM_RESUME 0.1626441478729248 370
78 linux_literal_casei 1 3 ucg (whitelist) ucg -i PM_RESUME 0.16270971298217773 370
79 linux_literal_casei 1 3 ucg (whitelist) ucg -i PM_RESUME 0.1596980094909668 370
80 linux_literal_default 1 3 rg rg PM_RESUME 0.14002084732055664 16
81 linux_literal_default 1 3 rg rg PM_RESUME 0.13782882690429688 16
82 linux_literal_default 1 3 rg rg PM_RESUME 0.13794231414794922 16
83 linux_literal_default 1 3 ag ag PM_RESUME 0.4623262882232666 16
84 linux_literal_default 1 3 ag ag PM_RESUME 0.419907808303833 16
85 linux_literal_default 1 3 ag ag PM_RESUME 0.44193005561828613 16
86 linux_literal_default 1 3 ucg ucg PM_RESUME 0.1634502410888672 16
87 linux_literal_default 1 3 ucg ucg PM_RESUME 0.17029428482055664 16
88 linux_literal_default 1 3 ucg ucg PM_RESUME 0.16076922416687012 16
89 linux_literal_default 1 3 pt pt PM_RESUME 0.15809178352355957 16
90 linux_literal_default 1 3 pt pt PM_RESUME 0.1554114818572998 16
91 linux_literal_default 1 3 pt pt PM_RESUME 0.15415430068969727 16
92 linux_literal_default 1 3 sift sift PM_RESUME 0.1160738468170166 16
93 linux_literal_default 1 3 sift sift PM_RESUME 0.11754369735717773 16
94 linux_literal_default 1 3 sift sift PM_RESUME 0.11825299263000488 16
95 linux_literal_default 1 3 git grep git grep PM_RESUME 0.18619132041931152 16 LC_ALL=en_US.UTF-8
96 linux_literal_default 1 3 git grep git grep PM_RESUME 0.16708111763000488 16 LC_ALL=en_US.UTF-8
97 linux_literal_default 1 3 git grep git grep PM_RESUME 0.20236515998840332 16 LC_ALL=en_US.UTF-8
98 linux_no_literal 1 3 rg (ignore) rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.34000611305236816 490
99 linux_no_literal 1 3 rg (ignore) rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.36969494819641113 490
100 linux_no_literal 1 3 rg (ignore) rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.3622872829437256 490
101 linux_no_literal 1 3 rg (ignore) (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.2572669982910156 490
102 linux_no_literal 1 3 rg (ignore) (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.3148176670074463 490
103 linux_no_literal 1 3 rg (ignore) (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.3092081546783447 490
104 linux_no_literal 1 3 ag (ignore) (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.7651598453521729 766
105 linux_no_literal 1 3 ag (ignore) (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.7487096786499023 766
106 linux_no_literal 1 3 ag (ignore) (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.7506840229034424 766
107 linux_no_literal 1 3 pt (ignore) (ASCII) pt -e \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 12.426137685775757 490
108 linux_no_literal 1 3 pt (ignore) (ASCII) pt -e \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 12.454124450683594 490
109 linux_no_literal 1 3 pt (ignore) (ASCII) pt -e \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 12.573740243911743 490
110 linux_no_literal 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 8.734328746795654 490
111 linux_no_literal 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 8.95349931716919 490
112 linux_no_literal 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 8.97816801071167 490
113 linux_no_literal 1 3 git grep (ignore) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 8.792009830474854 490 LC_ALL=en_US.UTF-8
114 linux_no_literal 1 3 git grep (ignore) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 8.744960308074951 490 LC_ALL=en_US.UTF-8
115 linux_no_literal 1 3 git grep (ignore) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 9.04098892211914 490 LC_ALL=en_US.UTF-8
116 linux_no_literal 1 3 git grep (ignore) (ASCII) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 1.8596012592315674 490 LC_ALL=C
117 linux_no_literal 1 3 git grep (ignore) (ASCII) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 1.824751853942871 490 LC_ALL=C
118 linux_no_literal 1 3 git grep (ignore) (ASCII) git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 1.9543235301971436 490 LC_ALL=C
119 linux_no_literal 1 3 rg (whitelist) rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.31849026679992676 419
120 linux_no_literal 1 3 rg (whitelist) rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.3028290271759033 419
121 linux_no_literal 1 3 rg (whitelist) rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.31795716285705566 419
122 linux_no_literal 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.22214102745056152 419
123 linux_no_literal 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.2748534679412842 419
124 linux_no_literal 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.2098088264465332 419
125 linux_no_literal 1 3 ucg (whitelist) (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.4494349956512451 416
126 linux_no_literal 1 3 ucg (whitelist) (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.44551706314086914 416
127 linux_no_literal 1 3 ucg (whitelist) (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} 0.4425935745239258 416
128 linux_re_literal_suffix 1 3 rg (ignore) rg -n [A-Z]+_RESUME 0.19018173217773438 1652
129 linux_re_literal_suffix 1 3 rg (ignore) rg -n [A-Z]+_RESUME 0.1422746181488037 1652
130 linux_re_literal_suffix 1 3 rg (ignore) rg -n [A-Z]+_RESUME 0.14041566848754883 1652
131 linux_re_literal_suffix 1 3 ag (ignore) ag -s [A-Z]+_RESUME 0.5190994739532471 1652
132 linux_re_literal_suffix 1 3 ag (ignore) ag -s [A-Z]+_RESUME 0.5290501117706299 1652
133 linux_re_literal_suffix 1 3 ag (ignore) ag -s [A-Z]+_RESUME 0.5360753536224365 1652
134 linux_re_literal_suffix 1 3 pt (ignore) pt -e [A-Z]+_RESUME 11.900719404220581 1652
135 linux_re_literal_suffix 1 3 pt (ignore) pt -e [A-Z]+_RESUME 11.905181646347046 1652
136 linux_re_literal_suffix 1 3 pt (ignore) pt -e [A-Z]+_RESUME 11.878832817077637 1652
137 linux_re_literal_suffix 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME 3.9338936805725098 1652
138 linux_re_literal_suffix 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME 3.971776247024536 1652
139 linux_re_literal_suffix 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME 4.010965585708618 1652
140 linux_re_literal_suffix 1 3 git grep (ignore) git grep -E -I -n [A-Z]+_RESUME 0.553400993347168 1652 LC_ALL=C
141 linux_re_literal_suffix 1 3 git grep (ignore) git grep -E -I -n [A-Z]+_RESUME 0.5757920742034912 1652 LC_ALL=C
142 linux_re_literal_suffix 1 3 git grep (ignore) git grep -E -I -n [A-Z]+_RESUME 0.6472165584564209 1652 LC_ALL=C
143 linux_re_literal_suffix 1 3 rg (whitelist) rg -n --no-ignore -tall [A-Z]+_RESUME 0.10109567642211914 1630
144 linux_re_literal_suffix 1 3 rg (whitelist) rg -n --no-ignore -tall [A-Z]+_RESUME 0.1010751724243164 1630
145 linux_re_literal_suffix 1 3 rg (whitelist) rg -n --no-ignore -tall [A-Z]+_RESUME 0.10259413719177246 1630
146 linux_re_literal_suffix 1 3 ucg (whitelist) ucg --nosmart-case [A-Z]+_RESUME 0.13558602333068848 1630
147 linux_re_literal_suffix 1 3 ucg (whitelist) ucg --nosmart-case [A-Z]+_RESUME 0.13765740394592285 1630
148 linux_re_literal_suffix 1 3 ucg (whitelist) ucg --nosmart-case [A-Z]+_RESUME 0.14018011093139648 1630
149 linux_unicode_greek 1 3 rg rg -n \p{Greek} 0.2655603885650635 23
150 linux_unicode_greek 1 3 rg rg -n \p{Greek} 0.2579922676086426 23
151 linux_unicode_greek 1 3 rg rg -n \p{Greek} 0.2389824390411377 23
152 linux_unicode_greek 1 3 pt pt -e \p{Greek} 11.789764881134033 23
153 linux_unicode_greek 1 3 pt pt -e \p{Greek} 11.717109680175781 23
154 linux_unicode_greek 1 3 pt pt -e \p{Greek} 11.714937448501587 23
155 linux_unicode_greek 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek} 2.732529401779175 23
156 linux_unicode_greek 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek} 2.782707452774048 23
157 linux_unicode_greek 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek} 2.8073642253875732 23
158 linux_unicode_greek_casei 1 3 rg rg -n -i \p{Greek} 0.29653406143188477 103
159 linux_unicode_greek_casei 1 3 rg rg -n -i \p{Greek} 0.24062681198120117 103
160 linux_unicode_greek_casei 1 3 rg rg -n -i \p{Greek} 0.24714946746826172 103
161 linux_unicode_greek_casei 1 3 pt pt -i -e \p{Greek} 11.754312515258789 23
162 linux_unicode_greek_casei 1 3 pt pt -i -e \p{Greek} 11.742995500564575 23
163 linux_unicode_greek_casei 1 3 pt pt -i -e \p{Greek} 11.763852596282959 23
164 linux_unicode_greek_casei 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek} 0.0018308162689208984
165 linux_unicode_greek_casei 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek} 0.0017769336700439453
166 linux_unicode_greek_casei 1 3 sift sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek} 0.0018434524536132812
167 linux_unicode_word 1 3 rg (ignore) rg -n \wAh 0.19392776489257812 186
168 linux_unicode_word 1 3 rg (ignore) rg -n \wAh 0.14665579795837402 186
169 linux_unicode_word 1 3 rg (ignore) rg -n \wAh 0.15625548362731934 186
170 linux_unicode_word 1 3 rg (ignore) (ASCII) rg -n (?-u)\wAh 0.14500045776367188 174
171 linux_unicode_word 1 3 rg (ignore) (ASCII) rg -n (?-u)\wAh 0.15199685096740723 174
172 linux_unicode_word 1 3 rg (ignore) (ASCII) rg -n (?-u)\wAh 0.14606475830078125 174
173 linux_unicode_word 1 3 ag (ignore) (ASCII) ag -s \wAh 0.47933006286621094 174
174 linux_unicode_word 1 3 ag (ignore) (ASCII) ag -s \wAh 0.4965095520019531 174
175 linux_unicode_word 1 3 ag (ignore) (ASCII) ag -s \wAh 0.4971892833709717 174
176 linux_unicode_word 1 3 pt (ignore) (ASCII) pt -e \wAh 12.043948650360107 174
177 linux_unicode_word 1 3 pt (ignore) (ASCII) pt -e \wAh 12.024799823760986 174
178 linux_unicode_word 1 3 pt (ignore) (ASCII) pt -e \wAh 12.032919883728027 174
179 linux_unicode_word 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \wAh 4.146677255630493 174
180 linux_unicode_word 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \wAh 4.05977988243103 174
181 linux_unicode_word 1 3 sift (ignore) (ASCII) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \wAh 4.246629238128662 174
182 linux_unicode_word 1 3 git grep (ignore) git grep -E -I -n \wAh 4.401025772094727 186 LC_ALL=en_US.UTF-8
183 linux_unicode_word 1 3 git grep (ignore) git grep -E -I -n \wAh 4.499484062194824 186 LC_ALL=en_US.UTF-8
184 linux_unicode_word 1 3 git grep (ignore) git grep -E -I -n \wAh 4.530885934829712 186 LC_ALL=en_US.UTF-8
185 linux_unicode_word 1 3 git grep (ignore) (ASCII) git grep -E -I -n \wAh 1.552142858505249 174 LC_ALL=C
186 linux_unicode_word 1 3 git grep (ignore) (ASCII) git grep -E -I -n \wAh 1.4553732872009277 174 LC_ALL=C
187 linux_unicode_word 1 3 git grep (ignore) (ASCII) git grep -E -I -n \wAh 1.3407535552978516 174 LC_ALL=C
188 linux_unicode_word 1 3 rg (whitelist) rg -n --no-ignore -tall \wAh 0.10183477401733398 180
189 linux_unicode_word 1 3 rg (whitelist) rg -n --no-ignore -tall \wAh 0.10535907745361328 180
190 linux_unicode_word 1 3 rg (whitelist) rg -n --no-ignore -tall \wAh 0.10527634620666504 180
191 linux_unicode_word 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\wAh 0.10268187522888184 168
192 linux_unicode_word 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\wAh 0.10159945487976074 168
193 linux_unicode_word 1 3 rg (whitelist) (ASCII) rg -n --no-ignore -tall (?-u)\wAh 0.09854245185852051 168
194 linux_unicode_word 1 3 ucg (ASCII) ucg --nosmart-case \wAh 0.17232871055603027 168
195 linux_unicode_word 1 3 ucg (ASCII) ucg --nosmart-case \wAh 0.17245817184448242 168
196 linux_unicode_word 1 3 ucg (ASCII) ucg --nosmart-case \wAh 0.1736738681793213 168
197 linux_word 1 3 rg (ignore) rg -n -w PM_RESUME 0.18302679061889648 6
198 linux_word 1 3 rg (ignore) rg -n -w PM_RESUME 0.14654874801635742 6
199 linux_word 1 3 rg (ignore) rg -n -w PM_RESUME 0.14666008949279785 6
200 linux_word 1 3 ag (ignore) ag -s -w PM_RESUME 0.43340468406677246 6
201 linux_word 1 3 ag (ignore) ag -s -w PM_RESUME 0.4431777000427246 6
202 linux_word 1 3 ag (ignore) ag -s -w PM_RESUME 0.4939415454864502 6
203 linux_word 1 3 pt (ignore) pt -w PM_RESUME 12.12212347984314 6
204 linux_word 1 3 pt (ignore) pt -w PM_RESUME 12.106850862503052 6
205 linux_word 1 3 pt (ignore) pt -w PM_RESUME 12.119231224060059 6
206 linux_word 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME 3.3320345878601074 6
207 linux_word 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME 3.2089524269104004 6
208 linux_word 1 3 sift (ignore) sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME 3.34165096282959 6
209 linux_word 1 3 git grep (ignore) git grep -E -I -n -w PM_RESUME 0.20112895965576172 6 LC_ALL=C
210 linux_word 1 3 git grep (ignore) git grep -E -I -n -w PM_RESUME 0.16607999801635742 6 LC_ALL=C
211 linux_word 1 3 git grep (ignore) git grep -E -I -n -w PM_RESUME 0.2049086093902588 6 LC_ALL=C
212 linux_word 1 3 rg (whitelist) rg -n -w --no-ignore -tall PM_RESUME 0.10440325736999512 6
213 linux_word 1 3 rg (whitelist) rg -n -w --no-ignore -tall PM_RESUME 0.09853243827819824 6
214 linux_word 1 3 rg (whitelist) rg -n -w --no-ignore -tall PM_RESUME 0.09580087661743164 6
215 linux_word 1 3 ucg (whitelist) ucg --nosmart-case -w PM_RESUME 0.16874432563781738 6
216 linux_word 1 3 ucg (whitelist) ucg --nosmart-case -w PM_RESUME 0.16241073608398438 6
217 linux_word 1 3 ucg (whitelist) ucg --nosmart-case -w PM_RESUME 0.1621534824371338 6
218 subtitles_en_alternate 1 3 rg (lines) rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5109667778015137 848
219 subtitles_en_alternate 1 3 rg (lines) rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.662921667098999 848
220 subtitles_en_alternate 1 3 rg (lines) rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.627272367477417 848
221 subtitles_en_alternate 1 3 ag (lines) ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.4915170669555664 848
222 subtitles_en_alternate 1 3 ag (lines) ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.294611930847168 848
223 subtitles_en_alternate 1 3 ag (lines) ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.475243330001831 848
224 subtitles_en_alternate 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.450028419494629 848
225 subtitles_en_alternate 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.266982078552246 848
226 subtitles_en_alternate 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.429199457168579 848
227 subtitles_en_alternate 1 3 grep (lines) grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.81933856010437 848 LC_ALL=C
228 subtitles_en_alternate 1 3 grep (lines) grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.829207420349121 848 LC_ALL=C
229 subtitles_en_alternate 1 3 grep (lines) grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.795469284057617 848 LC_ALL=C
230 subtitles_en_alternate 1 3 rg rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.3135373592376709 848
231 subtitles_en_alternate 1 3 rg rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.47072267532348633 848
232 subtitles_en_alternate 1 3 rg rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.3777759075164795 848
233 subtitles_en_alternate 1 3 grep grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.2277214527130127 848 LC_ALL=C
234 subtitles_en_alternate 1 3 grep grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.4641876220703125 848 LC_ALL=C
235 subtitles_en_alternate 1 3 grep grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.4201643466949463 848 LC_ALL=C
236 subtitles_en_alternate_casei 1 3 ag (ASCII) ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.925377368927002 862
237 subtitles_en_alternate_casei 1 3 ag (ASCII) ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.7743782997131348 862
238 subtitles_en_alternate_casei 1 3 ag (ASCII) ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.9031031131744385 862
239 subtitles_en_alternate_casei 1 3 ucg (ASCII) ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.902085542678833 862
240 subtitles_en_alternate_casei 1 3 ucg (ASCII) ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.9104111194610596 862
241 subtitles_en_alternate_casei 1 3 ucg (ASCII) ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.9407846927642822 862
242 subtitles_en_alternate_casei 1 3 grep (ASCII) grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.6935694217681885 862 LC_ALL=C
243 subtitles_en_alternate_casei 1 3 grep (ASCII) grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.7745134830474854 862 LC_ALL=C
244 subtitles_en_alternate_casei 1 3 grep (ASCII) grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.5532472133636475 862 LC_ALL=C
245 subtitles_en_alternate_casei 1 3 rg rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.3000056743621826 862
246 subtitles_en_alternate_casei 1 3 rg rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.46085786819458 862
247 subtitles_en_alternate_casei 1 3 rg rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.2774720191955566 862
248 subtitles_en_alternate_casei 1 3 grep grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 4.183770418167114 862 LC_ALL=en_US.UTF-8
249 subtitles_en_alternate_casei 1 3 grep grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 4.210017442703247 862 LC_ALL=en_US.UTF-8
250 subtitles_en_alternate_casei 1 3 grep grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 4.052750587463379 862 LC_ALL=en_US.UTF-8
251 subtitles_en_literal 1 3 rg rg Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.2422008514404297 629
252 subtitles_en_literal 1 3 rg rg Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.18678736686706543 629
253 subtitles_en_literal 1 3 rg rg Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.20187044143676758 629
254 subtitles_en_literal 1 3 rg (no mmap) rg --no-mmap Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.21189618110656738 629
255 subtitles_en_literal 1 3 rg (no mmap) rg --no-mmap Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.21378588676452637 629
256 subtitles_en_literal 1 3 rg (no mmap) rg --no-mmap Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.2638204097747803 629
257 subtitles_en_literal 1 3 pt pt -N Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.6680185794830322 629
258 subtitles_en_literal 1 3 pt pt -N Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.7018795013427734 629
259 subtitles_en_literal 1 3 pt pt -N Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.7135086059570312 629
260 subtitles_en_literal 1 3 sift sift Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.33170270919799805 629
261 subtitles_en_literal 1 3 sift sift Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.3204488754272461 629
262 subtitles_en_literal 1 3 sift sift Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.3302597999572754 629
263 subtitles_en_literal 1 3 grep grep -a Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5119576454162598 629 LC_ALL=C
264 subtitles_en_literal 1 3 grep grep -a Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.48076844215393066 629 LC_ALL=C
265 subtitles_en_literal 1 3 grep grep -a Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.6118988990783691 629 LC_ALL=C
266 subtitles_en_literal 1 3 rg (lines) rg -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.6149063110351562 629
267 subtitles_en_literal 1 3 rg (lines) rg -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.547245979309082 629
268 subtitles_en_literal 1 3 rg (lines) rg -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5441193580627441 629
269 subtitles_en_literal 1 3 ag (lines) ag -s Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.990401268005371 629
270 subtitles_en_literal 1 3 ag (lines) ag -s Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.9924650192260742 629
271 subtitles_en_literal 1 3 ag (lines) ag -s Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.807952642440796 629
272 subtitles_en_literal 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.772294282913208 629
273 subtitles_en_literal 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.8758792877197266 629
274 subtitles_en_literal 1 3 ucg (lines) ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.8043625354766846 629
275 subtitles_en_literal 1 3 pt (lines) pt Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.5409111976623535 629
276 subtitles_en_literal 1 3 pt (lines) pt Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.535851001739502 629
277 subtitles_en_literal 1 3 pt (lines) pt Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.6951041221618652 629
278 subtitles_en_literal 1 3 sift (lines) sift -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.7138817310333252 629
279 subtitles_en_literal 1 3 sift (lines) sift -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.727524995803833 629
280 subtitles_en_literal 1 3 sift (lines) sift -n Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.7202486991882324 629
281 subtitles_en_literal 1 3 grep (lines) grep -an Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.0228428840637207 629 LC_ALL=C
282 subtitles_en_literal 1 3 grep (lines) grep -an Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.9452800750732422 629 LC_ALL=C
283 subtitles_en_literal 1 3 grep (lines) grep -an Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.0286569595336914 629 LC_ALL=C
284 subtitles_en_literal_casei 1 3 rg rg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.36867737770080566 642
285 subtitles_en_literal_casei 1 3 rg rg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.391110897064209 642
286 subtitles_en_literal_casei 1 3 rg rg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.42432594299316406 642
287 subtitles_en_literal_casei 1 3 grep grep -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.2124955654144287 642 LC_ALL=en_US.UTF-8
288 subtitles_en_literal_casei 1 3 grep grep -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.288994789123535 642 LC_ALL=en_US.UTF-8
289 subtitles_en_literal_casei 1 3 grep grep -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.2279436588287354 642 LC_ALL=en_US.UTF-8
290 subtitles_en_literal_casei 1 3 grep (ASCII) grep -E -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5713660717010498 642 LC_ALL=C
291 subtitles_en_literal_casei 1 3 grep (ASCII) grep -E -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5478014945983887 642 LC_ALL=C
292 subtitles_en_literal_casei 1 3 grep (ASCII) grep -E -ai Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5502541065216064 642 LC_ALL=C
293 subtitles_en_literal_casei 1 3 rg (lines) rg -n -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5866222381591797 642
294 subtitles_en_literal_casei 1 3 rg (lines) rg -n -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5829083919525146 642
295 subtitles_en_literal_casei 1 3 rg (lines) rg -n -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.7458250522613525 642
296 subtitles_en_literal_casei 1 3 ag (lines) (ASCII) ag -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.8324756622314453 642
297 subtitles_en_literal_casei 1 3 ag (lines) (ASCII) ag -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.8361680507659912 642
298 subtitles_en_literal_casei 1 3 ag (lines) (ASCII) ag -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.017822265625 642
299 subtitles_en_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.9228289127349854 642
300 subtitles_en_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.9356215000152588 642
301 subtitles_en_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.9355306625366211 642
302 subtitles_en_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.46090102195739746 629
303 subtitles_en_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.41375064849853516 629
304 subtitles_en_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.4181649684906006 629
305 subtitles_en_literal_word 1 3 ag (ASCII) ag -sw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.8445067405700684 629
306 subtitles_en_literal_word 1 3 ag (ASCII) ag -sw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.805356740951538 629
307 subtitles_en_literal_word 1 3 ag (ASCII) ag -sw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.8274097442626953 629
308 subtitles_en_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.9036450386047363 629
309 subtitles_en_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.7601873874664307 629
310 subtitles_en_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.7341368198394775 629
311 subtitles_en_literal_word 1 3 grep (ASCII) grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.867140531539917 629 LC_ALL=C
312 subtitles_en_literal_word 1 3 grep (ASCII) grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.8452246189117432 629 LC_ALL=C
313 subtitles_en_literal_word 1 3 grep (ASCII) grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.8254234790802002 629 LC_ALL=C
314 subtitles_en_literal_word 1 3 rg rg -nw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.39222264289855957 629
315 subtitles_en_literal_word 1 3 rg rg -nw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5510556697845459 629
316 subtitles_en_literal_word 1 3 rg rg -nw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.439284086227417 629
317 subtitles_en_literal_word 1 3 grep grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.8688523769378662 629 LC_ALL=en_US.UTF-8
318 subtitles_en_literal_word 1 3 grep grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.0727341175079346 629 LC_ALL=en_US.UTF-8
319 subtitles_en_literal_word 1 3 grep grep -anw Sherlock Holmes /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.8665497303009033 629 LC_ALL=en_US.UTF-8
320 subtitles_en_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.2950611114501953 13
321 subtitles_en_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.226304769515991 13
322 subtitles_en_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.3140387535095215 13
323 subtitles_en_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.055910587310791 13
324 subtitles_en_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.032794952392578 13
325 subtitles_en_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 2.0602478981018066 13
326 subtitles_en_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 7.566168308258057 48
327 subtitles_en_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 7.360717535018921 48
328 subtitles_en_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 7.30781364440918 48
329 subtitles_en_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 6.13957142829895 13
330 subtitles_en_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 6.132368564605713 13
331 subtitles_en_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 5.929611921310425 13
332 subtitles_en_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.432003974914551 13 LC_ALL=C
333 subtitles_en_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.714038610458374 13 LC_ALL=C
334 subtitles_en_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.6915385723114014 13 LC_ALL=C
335 subtitles_en_surrounding_words 1 3 rg rg -n \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.42601513862609863 317
336 subtitles_en_surrounding_words 1 3 rg rg -n \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.561565637588501 317
337 subtitles_en_surrounding_words 1 3 rg rg -n \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5141217708587646 317
338 subtitles_en_surrounding_words 1 3 grep grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.3077969551086426 317 LC_ALL=en_US.UTF-8
339 subtitles_en_surrounding_words 1 3 grep grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.1768431663513184 317 LC_ALL=en_US.UTF-8
340 subtitles_en_surrounding_words 1 3 grep grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.0883615016937256 317 LC_ALL=en_US.UTF-8
341 subtitles_en_surrounding_words 1 3 rg (ASCII) rg -n (?-u)\w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5061089992523193 317
342 subtitles_en_surrounding_words 1 3 rg (ASCII) rg -n (?-u)\w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.4004178047180176 317
343 subtitles_en_surrounding_words 1 3 rg (ASCII) rg -n (?-u)\w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 0.5536422729492188 317
344 subtitles_en_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 4.981522798538208 323
345 subtitles_en_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 4.83101487159729 323
346 subtitles_en_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 5.025806427001953 323
347 subtitles_en_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.906707286834717 317
348 subtitles_en_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.8826284408569336 317
349 subtitles_en_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 3.852736711502075 317
350 subtitles_en_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.262470006942749 317 LC_ALL=C
351 subtitles_en_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.1661438941955566 317 LC_ALL=C
352 subtitles_en_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Holmes\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en 1.1648437976837158 317 LC_ALL=C
353 subtitles_ru_alternate 1 3 rg (lines) rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.79972243309021 691
354 subtitles_ru_alternate 1 3 rg (lines) rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.629694938659668 691
355 subtitles_ru_alternate 1 3 rg (lines) rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.8325402736663818 691
356 subtitles_ru_alternate 1 3 ag (lines) ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.124853849411011 691
357 subtitles_ru_alternate 1 3 ag (lines) ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.0995543003082275 691
358 subtitles_ru_alternate 1 3 ag (lines) ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.105457544326782 691
359 subtitles_ru_alternate 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.491947650909424 691
360 subtitles_ru_alternate 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.544341802597046 691
361 subtitles_ru_alternate 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.6295418739318848 691
362 subtitles_ru_alternate 1 3 grep (lines) grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.948693513870239 691 LC_ALL=C
363 subtitles_ru_alternate 1 3 grep (lines) grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.991183280944824 691 LC_ALL=C
364 subtitles_ru_alternate 1 3 grep (lines) grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 7.004202842712402 691 LC_ALL=C
365 subtitles_ru_alternate 1 3 rg rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.1708271503448486 691
366 subtitles_ru_alternate 1 3 rg rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.3341143131256104 691
367 subtitles_ru_alternate 1 3 rg rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.3589985370635986 691
368 subtitles_ru_alternate 1 3 grep grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.3860955238342285 691 LC_ALL=C
369 subtitles_ru_alternate 1 3 grep grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.437295436859131 691 LC_ALL=C
370 subtitles_ru_alternate 1 3 grep grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.34372615814209 691 LC_ALL=C
371 subtitles_ru_alternate_casei 1 3 ag (ASCII) ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.100299119949341 691
372 subtitles_ru_alternate_casei 1 3 ag (ASCII) ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.343926668167114 691
373 subtitles_ru_alternate_casei 1 3 ag (ASCII) ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.247299432754517 691
374 subtitles_ru_alternate_casei 1 3 ucg (ASCII) ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.6179757118225098 691
375 subtitles_ru_alternate_casei 1 3 ucg (ASCII) ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.438668727874756 691
376 subtitles_ru_alternate_casei 1 3 ucg (ASCII) ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.6296229362487793 691
377 subtitles_ru_alternate_casei 1 3 grep (ASCII) grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.816138744354248 691 LC_ALL=C
378 subtitles_ru_alternate_casei 1 3 grep (ASCII) grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 7.005900859832764 691 LC_ALL=C
379 subtitles_ru_alternate_casei 1 3 grep (ASCII) grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.96263861656189 691 LC_ALL=C
380 subtitles_ru_alternate_casei 1 3 rg rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.222437858581543 735
381 subtitles_ru_alternate_casei 1 3 rg rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.260664463043213 735
382 subtitles_ru_alternate_casei 1 3 rg rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 4.040424823760986 735
383 subtitles_ru_alternate_casei 1 3 grep grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 7.112156391143799 735 LC_ALL=en_US.UTF-8
384 subtitles_ru_alternate_casei 1 3 grep grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 7.066831350326538 735 LC_ALL=en_US.UTF-8
385 subtitles_ru_alternate_casei 1 3 grep grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.983258962631226 735 LC_ALL=en_US.UTF-8
386 subtitles_ru_literal 1 3 rg rg Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.3009657859802246 583
387 subtitles_ru_literal 1 3 rg rg Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.31114768981933594 583
388 subtitles_ru_literal 1 3 rg rg Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.3145453929901123 583
389 subtitles_ru_literal 1 3 rg (no mmap) rg --no-mmap Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.3670217990875244 583
390 subtitles_ru_literal 1 3 rg (no mmap) rg --no-mmap Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.39557576179504395 583
391 subtitles_ru_literal 1 3 rg (no mmap) rg --no-mmap Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.38857460021972656 583
392 subtitles_ru_literal 1 3 pt pt -N Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 5.653504133224487 583
393 subtitles_ru_literal 1 3 pt pt -N Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 5.440903663635254 583
394 subtitles_ru_literal 1 3 pt pt -N Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 5.604345321655273 583
395 subtitles_ru_literal 1 3 sift sift Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.333267450332642 583
396 subtitles_ru_literal 1 3 sift sift Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.3738181591033936 583
397 subtitles_ru_literal 1 3 sift sift Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.604928970336914 583
398 subtitles_ru_literal 1 3 grep grep -a Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.7382421493530273 583 LC_ALL=C
399 subtitles_ru_literal 1 3 grep grep -a Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.7205381393432617 583 LC_ALL=C
400 subtitles_ru_literal 1 3 grep grep -a Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.8509528636932373 583 LC_ALL=C
401 subtitles_ru_literal 1 3 rg (lines) rg -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.6589868068695068 583
402 subtitles_ru_literal 1 3 rg (lines) rg -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.857933759689331 583
403 subtitles_ru_literal 1 3 rg (lines) rg -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.7283596992492676 583
404 subtitles_ru_literal 1 3 ag (lines) ag -s Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 3.111611843109131 583
405 subtitles_ru_literal 1 3 ag (lines) ag -s Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 3.1084604263305664 583
406 subtitles_ru_literal 1 3 ag (lines) ag -s Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.993370771408081 583
407 subtitles_ru_literal 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.8463020324707031 583
408 subtitles_ru_literal 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.8160367012023926 583
409 subtitles_ru_literal 1 3 ucg (lines) ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.9012954235076904 583
410 subtitles_ru_literal 1 3 pt (lines) pt Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 5.590208530426025 583
411 subtitles_ru_literal 1 3 pt (lines) pt Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 5.712487697601318 583
412 subtitles_ru_literal 1 3 pt (lines) pt Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 5.628024339675903 583
413 subtitles_ru_literal 1 3 sift (lines) sift -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.999194145202637 583
414 subtitles_ru_literal 1 3 sift (lines) sift -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.639494895935059 583
415 subtitles_ru_literal 1 3 sift (lines) sift -n Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.6554951667785645 583
416 subtitles_ru_literal 1 3 grep (lines) grep -an Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.3319404125213623 583 LC_ALL=C
417 subtitles_ru_literal 1 3 grep (lines) grep -an Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.3712143898010254 583 LC_ALL=C
418 subtitles_ru_literal 1 3 grep (lines) grep -an Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.2382845878601074 583 LC_ALL=C
419 subtitles_ru_literal_casei 1 3 rg rg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.2365717887878418 604
420 subtitles_ru_literal_casei 1 3 rg rg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.2306108474731445 604
421 subtitles_ru_literal_casei 1 3 rg rg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.22041654586792 604
422 subtitles_ru_literal_casei 1 3 grep grep -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.636392116546631 604 LC_ALL=en_US.UTF-8
423 subtitles_ru_literal_casei 1 3 grep grep -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.447664976119995 604 LC_ALL=en_US.UTF-8
424 subtitles_ru_literal_casei 1 3 grep grep -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 6.47466516494751 604 LC_ALL=en_US.UTF-8
425 subtitles_ru_literal_casei 1 3 grep (ASCII) grep -E -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.8679373264312744 583 LC_ALL=C
426 subtitles_ru_literal_casei 1 3 grep (ASCII) grep -E -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.8400778770446777 583 LC_ALL=C
427 subtitles_ru_literal_casei 1 3 grep (ASCII) grep -E -ai Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.8912734985351562 583 LC_ALL=C
428 subtitles_ru_literal_casei 1 3 rg (lines) rg -n -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.6649067401885986 604
429 subtitles_ru_literal_casei 1 3 rg (lines) rg -n -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.472435712814331 604
430 subtitles_ru_literal_casei 1 3 rg (lines) rg -n -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.5518934726715088 604
431 subtitles_ru_literal_casei 1 3 ag (lines) (ASCII) ag -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.6329071521759033
432 subtitles_ru_literal_casei 1 3 ag (lines) (ASCII) ag -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.6236186027526855
433 subtitles_ru_literal_casei 1 3 ag (lines) (ASCII) ag -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.744124174118042
434 subtitles_ru_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.842088222503662 583
435 subtitles_ru_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.6797516345977783 583
436 subtitles_ru_literal_casei 1 3 ucg (lines) (ASCII) ucg -i Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.86281418800354 583
437 subtitles_ru_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.3059053421020508
438 subtitles_ru_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.3220036029815674
439 subtitles_ru_literal_word 1 3 rg (ASCII) rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.3317573070526123
440 subtitles_ru_literal_word 1 3 ag (ASCII) ag -sw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.790125846862793
441 subtitles_ru_literal_word 1 3 ag (ASCII) ag -sw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.8004007339477539
442 subtitles_ru_literal_word 1 3 ag (ASCII) ag -sw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.7884745597839355
443 subtitles_ru_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.8595643043518066 583
444 subtitles_ru_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.8338594436645508 583
445 subtitles_ru_literal_word 1 3 ucg (ASCII) ucg --nosmart-case Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.6697683334350586 583
446 subtitles_ru_literal_word 1 3 grep (ASCII) grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.1608448028564453 583 LC_ALL=C
447 subtitles_ru_literal_word 1 3 grep (ASCII) grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.3229436874389648 583 LC_ALL=C
448 subtitles_ru_literal_word 1 3 grep (ASCII) grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.3650012016296387 583 LC_ALL=C
449 subtitles_ru_literal_word 1 3 rg rg -nw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.840968132019043 579
450 subtitles_ru_literal_word 1 3 rg rg -nw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.7012484073638916 579
451 subtitles_ru_literal_word 1 3 rg rg -nw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.6782803535461426 579
452 subtitles_ru_literal_word 1 3 grep grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.3308250904083252 579 LC_ALL=en_US.UTF-8
453 subtitles_ru_literal_word 1 3 grep grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.2687301635742188 579 LC_ALL=en_US.UTF-8
454 subtitles_ru_literal_word 1 3 grep grep -anw Шерлок Холмс /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.317870855331421 579 LC_ALL=en_US.UTF-8
455 subtitles_ru_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 3.8553390502929688 41
456 subtitles_ru_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 3.6567201614379883 41
457 subtitles_ru_no_literal 1 3 rg rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 3.6484830379486084 41
458 subtitles_ru_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.968876838684082
459 subtitles_ru_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 3.0976366996765137
460 subtitles_ru_no_literal 1 3 rg (ASCII) rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.9159646034240723
461 subtitles_ru_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.8425374031066895
462 subtitles_ru_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.0483176708221436
463 subtitles_ru_no_literal 1 3 ag (ASCII) ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.0838112831115723
464 subtitles_ru_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.510307550430298
465 subtitles_ru_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.542471408843994
466 subtitles_ru_no_literal 1 3 ucg (ASCII) ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.5069386959075928
467 subtitles_ru_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.0888967514038086 LC_ALL=C
468 subtitles_ru_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.119218349456787 LC_ALL=C
469 subtitles_ru_no_literal 1 3 grep (ASCII) grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.0531933307647705 LC_ALL=C
470 subtitles_ru_surrounding_words 1 3 rg rg -n \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.792813777923584 278
471 subtitles_ru_surrounding_words 1 3 rg rg -n \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.8660504817962646 278
472 subtitles_ru_surrounding_words 1 3 rg rg -n \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 0.8515620231628418 278
473 subtitles_ru_surrounding_words 1 3 grep grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.4405500888824463 278 LC_ALL=en_US.UTF-8
474 subtitles_ru_surrounding_words 1 3 grep grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.6386635303497314 278 LC_ALL=en_US.UTF-8
475 subtitles_ru_surrounding_words 1 3 grep grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.5895426273345947 278 LC_ALL=en_US.UTF-8
476 subtitles_ru_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.032708168029785
477 subtitles_ru_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.927478551864624
478 subtitles_ru_surrounding_words 1 3 ag (ASCII) ag -s \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.019101619720459
479 subtitles_ru_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.6226632595062256
480 subtitles_ru_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.5062124729156494
481 subtitles_ru_surrounding_words 1 3 ucg (ASCII) ucg --nosmart-case \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 2.5160763263702393
482 subtitles_ru_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.613976240158081 LC_ALL=C
483 subtitles_ru_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.5636706352233887 LC_ALL=C
484 subtitles_ru_surrounding_words 1 3 grep (ASCII) grep -E -an \w+\s+Холмс\s+\w+ /data/benchsuite/subtitles/OpenSubtitles2016.raw.ru 1.4378304481506348 LC_ALL=C

View File

@@ -0,0 +1,235 @@
linux_alternates (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
-------------------------------------------------------------------------
rg (ignore) 0.159 +/- 0.002 (lines: 68)
ag (ignore) 0.557 +/- 0.009 (lines: 68)
git grep (ignore) 0.252 +/- 0.005 (lines: 68)
rg (whitelist)* 0.103 +/- 0.001 (lines: 68)*
ucg (whitelist) 0.155 +/- 0.002 (lines: 68)
linux_alternates_casei (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
-------------------------------------------------------------------------------
rg (ignore) 0.161 +/- 0.001 (lines: 160)
ag (ignore) 0.628 +/- 0.040 (lines: 160)
git grep (ignore) 0.940 +/- 0.109 (lines: 160)
rg (whitelist)* 0.123 +/- 0.010 (lines: 160)*
ucg (whitelist) 0.240 +/- 0.002 (lines: 160)
linux_literal (pattern: PM_RESUME)
----------------------------------
rg (ignore) 0.159 +/- 0.015 (lines: 16)
rg (ignore) (mmap) 0.389 +/- 0.009 (lines: 16)
ag (ignore) (mmap) 0.574 +/- 0.138 (lines: 16)
pt (ignore) 0.157 +/- 0.006 (lines: 16)
sift (ignore) 0.346 +/- 0.007 (lines: 16)
git grep (ignore) 0.201 +/- 0.011 (lines: 16)
rg (whitelist)* 0.104 +/- 0.003 (lines: 16)*
ucg (whitelist) 0.169 +/- 0.002 (lines: 16)
linux_literal_casei (pattern: PM_RESUME)
----------------------------------------
rg (ignore) 0.155 +/- 0.009 (lines: 370)
rg (ignore) (mmap) 0.393 +/- 0.005 (lines: 370)
ag (ignore) (mmap) 0.462 +/- 0.035 (lines: 370)
pt (ignore) 11.936 +/- 0.106 (lines: 370)
sift (ignore) 0.370 +/- 0.004 (lines: 370)
git grep (ignore) 0.190 +/- 0.006 (lines: 370)
rg (whitelist)* 0.109 +/- 0.004 (lines: 370)*
ucg (whitelist) 0.162 +/- 0.002 (lines: 370)
linux_literal_default (pattern: PM_RESUME)
------------------------------------------
rg 0.139 +/- 0.001 (lines: 16)
ag 0.441 +/- 0.021 (lines: 16)
ucg 0.165 +/- 0.005 (lines: 16)
pt 0.156 +/- 0.002 (lines: 16)
sift* 0.117 +/- 0.001 (lines: 16)*
git grep 0.185 +/- 0.018 (lines: 16)
linux_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
-----------------------------------------------------------------
rg (ignore) 0.357 +/- 0.015 (lines: 490)
rg (ignore) (ASCII) 0.294 +/- 0.032 (lines: 490)
ag (ignore) (ASCII) 0.755 +/- 0.009 (lines: 766)
pt (ignore) (ASCII) 12.485 +/- 0.078 (lines: 490)
sift (ignore) (ASCII) 8.889 +/- 0.134 (lines: 490)
git grep (ignore) 8.859 +/- 0.159 (lines: 490)
git grep (ignore) (ASCII) 1.880 +/- 0.067 (lines: 490)
rg (whitelist) 0.313 +/- 0.009 (lines: 419)
rg (whitelist) (ASCII)* 0.236 +/- 0.035 (lines: 419)*
ucg (whitelist) (ASCII) 0.446 +/- 0.003 (lines: 416)
linux_re_literal_suffix (pattern: [A-Z]+_RESUME)
------------------------------------------------
rg (ignore) 0.158 +/- 0.028 (lines: 1652)
ag (ignore) 0.528 +/- 0.009 (lines: 1652)
pt (ignore) 11.895 +/- 0.014 (lines: 1652)
sift (ignore) 3.972 +/- 0.039 (lines: 1652)
git grep (ignore) 0.592 +/- 0.049 (lines: 1652)
rg (whitelist)* 0.102 +/- 0.001 (lines: 1630)*
ucg (whitelist) 0.138 +/- 0.002 (lines: 1630)
linux_unicode_greek (pattern: \p{Greek})
----------------------------------------
rg* 0.254 +/- 0.014 (lines: 23)*
pt 11.741 +/- 0.043 (lines: 23)
sift 2.774 +/- 0.038 (lines: 23)
linux_unicode_greek_casei (pattern: \p{Greek})
----------------------------------------------
rg 0.261 +/- 0.031 (lines: 103)
pt 11.754 +/- 0.010 (lines: 23)
sift* 0.002 +/- 0.000 (lines: 0)*
linux_unicode_word (pattern: \wAh)
----------------------------------
rg (ignore) 0.166 +/- 0.025 (lines: 186)
rg (ignore) (ASCII) 0.148 +/- 0.004 (lines: 174)
ag (ignore) (ASCII) 0.491 +/- 0.010 (lines: 174)
pt (ignore) (ASCII) 12.034 +/- 0.010 (lines: 174)
sift (ignore) (ASCII) 4.151 +/- 0.094 (lines: 174)
git grep (ignore) 4.477 +/- 0.068 (lines: 186)
git grep (ignore) (ASCII) 1.449 +/- 0.106 (lines: 174)
rg (whitelist) 0.104 +/- 0.002 (lines: 180)
rg (whitelist) (ASCII)* 0.101 +/- 0.002 (lines: 168)*
ucg (ASCII) 0.173 +/- 0.001 (lines: 168)
linux_word (pattern: PM_RESUME)
-------------------------------
rg (ignore) 0.159 +/- 0.021 (lines: 6)
ag (ignore) 0.457 +/- 0.032 (lines: 6)
pt (ignore) 12.116 +/- 0.008 (lines: 6)
sift (ignore) 3.294 +/- 0.074 (lines: 6)
git grep (ignore) 0.191 +/- 0.021 (lines: 6)
rg (whitelist)* 0.100 +/- 0.004 (lines: 6)*
ucg (whitelist) 0.164 +/- 0.004 (lines: 6)
subtitles_en_alternate (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
---------------------------------------------------------------------------------------------------------------
rg (lines) 0.600 +/- 0.079 (lines: 848)
ag (lines) 2.420 +/- 0.109 (lines: 848)
ucg (lines) 1.382 +/- 0.100 (lines: 848)
grep (lines) 2.815 +/- 0.017 (lines: 848)
rg* 0.387 +/- 0.079 (lines: 848)*
grep 2.371 +/- 0.126 (lines: 848)
subtitles_en_alternate_casei (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
---------------------------------------------------------------------------------------------------------------------
ag (ASCII) 3.868 +/- 0.082 (lines: 862)
ucg (ASCII) 2.918 +/- 0.020 (lines: 862)
grep (ASCII) 3.674 +/- 0.112 (lines: 862)
rg* 2.346 +/- 0.100 (lines: 862)*
grep 4.149 +/- 0.084 (lines: 862)
subtitles_en_literal (pattern: Sherlock Holmes)
-----------------------------------------------
rg* 0.210 +/- 0.029 (lines: 629)*
rg (no mmap) 0.230 +/- 0.029 (lines: 629)
pt 1.694 +/- 0.024 (lines: 629)
sift 0.327 +/- 0.006 (lines: 629)
grep 0.535 +/- 0.069 (lines: 629)
rg (lines) 0.569 +/- 0.040 (lines: 629)
ag (lines) 1.930 +/- 0.106 (lines: 629)
ucg (lines) 0.818 +/- 0.053 (lines: 629)
pt (lines) 1.591 +/- 0.091 (lines: 629)
sift (lines) 0.721 +/- 0.007 (lines: 629)
grep (lines) 0.999 +/- 0.047 (lines: 629)
subtitles_en_literal_casei (pattern: Sherlock Holmes)
-----------------------------------------------------
rg* 0.395 +/- 0.028 (lines: 642)*
grep 3.243 +/- 0.040 (lines: 642)
grep (ASCII) 0.556 +/- 0.013 (lines: 642)
rg (lines) 0.638 +/- 0.093 (lines: 642)
ag (lines) (ASCII) 1.895 +/- 0.106 (lines: 642)
ucg (lines) (ASCII) 0.931 +/- 0.007 (lines: 642)
subtitles_en_literal_word (pattern: Sherlock Holmes)
----------------------------------------------------
rg (ASCII) 0.431 +/- 0.026 (lines: 629)*
ag (ASCII) 1.826 +/- 0.020 (lines: 629)
ucg (ASCII) 0.799 +/- 0.091 (lines: 629)
grep (ASCII) 0.846 +/- 0.021 (lines: 629)
rg* 0.461 +/- 0.082 (lines: 629)
grep 0.936 +/- 0.118 (lines: 629)
subtitles_en_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
----------------------------------------------------------------------------------------
rg 2.278 +/- 0.046 (lines: 13)
rg (ASCII)* 2.050 +/- 0.015 (lines: 13)*
ag (ASCII) 7.412 +/- 0.136 (lines: 48)
ucg (ASCII) 6.067 +/- 0.119 (lines: 13)
grep (ASCII) 3.613 +/- 0.157 (lines: 13)
subtitles_en_surrounding_words (pattern: \w+\s+Holmes\s+\w+)
------------------------------------------------------------
rg 0.501 +/- 0.069 (lines: 317)
grep 1.191 +/- 0.110 (lines: 317)
rg (ASCII)* 0.487 +/- 0.078 (lines: 317)*
ag (ASCII) 4.946 +/- 0.102 (lines: 323)
ucg (ASCII) 3.881 +/- 0.027 (lines: 317)
grep (ASCII) 1.198 +/- 0.056 (lines: 317)
subtitles_ru_alternate (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
-----------------------------------------------------------------------------------------------------------
rg (lines) 1.754 +/- 0.109 (lines: 691)
ag (lines) 4.110 +/- 0.013 (lines: 691)
ucg (lines) 2.555 +/- 0.069 (lines: 691)
grep (lines) 6.981 +/- 0.029 (lines: 691)
rg* 1.288 +/- 0.102 (lines: 691)*
grep 6.389 +/- 0.047 (lines: 691)
subtitles_ru_alternate_casei (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
-----------------------------------------------------------------------------------------------------------------
ag (ASCII) 4.231 +/- 0.123 (lines: 691)
ucg (ASCII)* 2.562 +/- 0.107 (lines: 691)*
grep (ASCII) 6.928 +/- 0.099 (lines: 691)
rg 4.175 +/- 0.118 (lines: 735)
grep 7.054 +/- 0.065 (lines: 735)
subtitles_ru_literal (pattern: Шерлок Холмс)
--------------------------------------------
rg* 0.309 +/- 0.007 (lines: 583)*
rg (no mmap) 0.384 +/- 0.015 (lines: 583)
pt 5.566 +/- 0.111 (lines: 583)
sift 6.437 +/- 0.147 (lines: 583)
grep 0.770 +/- 0.071 (lines: 583)
rg (lines) 0.748 +/- 0.101 (lines: 583)
ag (lines) 3.071 +/- 0.067 (lines: 583)
ucg (lines) 1.855 +/- 0.043 (lines: 583)
pt (lines) 5.644 +/- 0.063 (lines: 583)
sift (lines) 6.765 +/- 0.203 (lines: 583)
grep (lines) 1.314 +/- 0.068 (lines: 583)
subtitles_ru_literal_casei (pattern: Шерлок Холмс)
--------------------------------------------------
rg 1.229 +/- 0.008 (lines: 604)
grep 6.520 +/- 0.102 (lines: 604)
grep (ASCII) 0.866 +/- 0.026 (lines: 583)
rg (lines) 1.563 +/- 0.097 (lines: 604)
ag (lines) (ASCII)* 0.667 +/- 0.067 (lines: 0)*
ucg (lines) (ASCII) 1.795 +/- 0.100 (lines: 583)
subtitles_ru_literal_word (pattern: Шерлок Холмс)
-------------------------------------------------
rg (ASCII)* 0.320 +/- 0.013 (lines: 0)*
ag (ASCII) 0.793 +/- 0.006 (lines: 0)
ucg (ASCII) 1.788 +/- 0.103 (lines: 583)
grep (ASCII) 1.283 +/- 0.108 (lines: 583)
rg 0.740 +/- 0.088 (lines: 579)
grep 1.306 +/- 0.033 (lines: 579)
subtitles_ru_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
----------------------------------------------------------------------------------------
rg 3.720 +/- 0.117 (lines: 41)
rg (ASCII) 2.994 +/- 0.093 (lines: 0)
ag (ASCII)* 1.992 +/- 0.130 (lines: 0)*
ucg (ASCII) 2.520 +/- 0.020 (lines: 0)
grep (ASCII) 2.087 +/- 0.033 (lines: 0)
subtitles_ru_surrounding_words (pattern: \w+\s+Холмс\s+\w+)
-----------------------------------------------------------
rg* 0.837 +/- 0.039 (lines: 278)*
grep 1.556 +/- 0.103 (lines: 278)
ag (ASCII) 1.993 +/- 0.057 (lines: 0)
ucg (ASCII) 2.548 +/- 0.065 (lines: 0)
grep (ASCII) 1.538 +/- 0.091 (lines: 0)

View File

@@ -6,23 +6,22 @@ set -ex
# Generate artifacts for release
mk_artifacts() {
RUSTFLAGS="-C target-feature=+ssse3" cargo build --target $TARGET --release --features simd-accel
RUSTFLAGS="-C target-feature=+ssse3" \
cargo build --target $TARGET --release --features simd-accel
}
mk_tarball() {
# create a "staging" directory
local td=$(mktempd)
local out_dir=$(pwd)
local name="${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}"
mkdir "$td/$name"
# TODO update this part to copy the artifacts that make sense for your project
# NOTE All Cargo build artifacts will be under the 'target/$TARGET/{debug,release}'
cp target/$TARGET/release/xrep $td
cp target/$TARGET/release/rg "$td/$name/"
cp {doc/rg.1,README.md,UNLICENSE,COPYING,LICENSE-MIT} "$td/$name/"
pushd $td
# release tarball will look like 'rust-everywhere-v1.2.3-x86_64-unknown-linux-gnu.tar.gz'
tar czf $out_dir/${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}.tar.gz *
tar czf "$out_dir/$name.tar.gz" *
popd
rm -r $td
}

View File

@@ -11,42 +11,25 @@ disable_cross_doctests() {
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew install gnu-sed --default-names
fi
find src -name '*.rs' -type f | xargs sed -i -e 's:\(//.\s*```\):\1 ignore,:g'
fi
}
# TODO modify this function as you see fit
# PROTIP Always pass `--target $TARGET` to cargo commands, this makes cargo output build artifacts
# to target/$TARGET/{debug,release} which can reduce the number of needed conditionals in the
# `before_deploy`/packaging phase
run_test_suite() {
case $TARGET in
# configure emulation for transparent execution of foreign binaries
aarch64-unknown-linux-gnu)
export QEMU_LD_PREFIX=/usr/aarch64-linux-gnu
;;
arm*-unknown-linux-gnueabihf)
export QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf
;;
*)
;;
esac
if [ ! -z "$QEMU_LD_PREFIX" ]; then
# Run tests on a single thread when using QEMU user emulation
export RUST_TEST_THREADS=1
fi
cargo clean --target $TARGET --verbose
cargo build --target $TARGET --verbose
cargo test --target $TARGET
cargo test --target $TARGET --verbose
cargo build --target $TARGET --verbose --manifest-path grep/Cargo.toml
cargo test --target $TARGET --verbose --manifest-path grep/Cargo.toml
cargo build --target $TARGET --verbose --manifest-path globset/Cargo.toml
cargo test --target $TARGET --verbose --manifest-path globset/Cargo.toml
# sanity check the file type
file target/$TARGET/debug/xrep
file target/$TARGET/debug/rg
}
main() {
disable_cross_doctests
# disable_cross_doctests
run_test_suite
}

25
ci/sha256.sh Normal file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
set -e
if [ $# != 1 ]; then
echo "Usage: $(basename $0) version" >&2
exit 1
fi
version="$1"
# Linux and Darwin builds.
for arch in i686 x86_64; do
for target in apple-darwin unknown-linux-musl; do
url="https://github.com/BurntSushi/ripgrep/releases/download/$version/ripgrep-$version-$arch-$target.tar.gz"
sha=$(curl -sfSL "$url" | sha256sum)
echo "$version-$arch-$target $sha"
done
done
# Source.
for ext in zip tar.gz; do
url="https://github.com/BurntSushi/ripgrep/archive/$version.$ext"
sha=$(curl -sfSL "$url" | sha256sum)
echo "source.$ext $sha"
done

View File

@@ -1,4 +1,5 @@
#!/bin/sh
export RUSTFLAGS="-C target-feature=+ssse3"
# export RUSTFLAGS="-C target-cpu=native"
cargo build --release --features simd-accel

View File

@@ -1,11 +0,0 @@
--langdef=Rust
--langmap=Rust:.rs
--regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/
--regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/
--regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/
--regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/
--regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,modules,module names/
--regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,consts,static constants/
--regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,traits,traits/
--regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]+<.*>)?[ \t]+([a-zA-Z0-9_]+)/\3/i,impls,trait implementations/
--regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macros,macro definitions/

4
doc/convert-to-man Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
pandoc -s -t man rg.1.md -o rg.1
sed -i 's/\.TH.*/.TH "rg" "1"/g' rg.1

324
doc/rg.1 Normal file
View File

@@ -0,0 +1,324 @@
.\" Automatically generated by Pandoc 1.17.2
.\"
.TH "rg" "1"
.hy
.SH NAME
.PP
rg \- recursively search current directory for lines matching a pattern
.SH SYNOPSIS
.PP
rg [\f[I]options\f[]] \-e PATTERN ...
[\f[I]<\f[]path\f[I]> ...\f[]]
.PP
rg [\f[I]options\f[]] <\f[I]pattern\f[]> [\f[I]<\f[]path\f[I]> ...\f[]]
.PP
rg [\f[I]options\f[]] \-\-files [\f[I]<\f[]path\f[I]> ...\f[]]
.PP
rg [\f[I]options\f[]] \-\-type\-list
.PP
rg [\f[I]options\f[]] \-\-help
.PP
rg [\f[I]options\f[]] \-\-version
.SH DESCRIPTION
.PP
rg (ripgrep) combines the usability of The Silver Searcher (an ack
clone) with the raw speed of grep.
.SH COMMON OPTIONS
.TP
.B \-a, \-\-text
Search binary files as if they were text.
.RS
.RE
.TP
.B \-c, \-\-count
Only show count of line matches for each file.
.RS
.RE
.TP
.B \-\-color \f[I]WHEN\f[]
Whether to use coloring in match.
Valid values are never, always or auto.
[default: auto]
.RS
.RE
.TP
.B \-e, \-\-regexp \f[I]PATTERN\f[] ...
Use PATTERN to search.
This option can be provided multiple times, where all patterns given are
searched.
.RS
.RE
.TP
.B \-F, \-\-fixed\-strings
Treat the pattern as a literal string instead of a regular expression.
.RS
.RE
.TP
.B \-g, \-\-glob \f[I]GLOB\f[] ...
Include or exclude files for searching that match the given glob.
This always overrides any other ignore logic.
Multiple glob flags may be used.
Globbing rules match .gitignore globs.
Precede a glob with a \[aq]!\[aq] to exclude it.
.RS
.RE
.TP
.B \-h, \-\-help
Show this usage message.
.RS
.RE
.TP
.B \-i, \-\-ignore\-case
Case insensitive search.
Overridden by \-\-case\-sensitive.
.RS
.RE
.TP
.B \-n, \-\-line\-number
Show line numbers (1\-based).
This is enabled by default at a tty.
.RS
.RE
.TP
.B \-N, \-\-no\-line\-number
Suppress line numbers.
.RS
.RE
.TP
.B \-q, \-\-quiet
Do not print anything to stdout.
If a match is found in a file, stop searching that file.
.RS
.RE
.TP
.B \-t, \-\-type \f[I]TYPE\f[] ...
Only search files matching TYPE.
Multiple type flags may be provided.
Use the \-\-type\-list flag to list all available types.
.RS
.RE
.TP
.B \-T, \-\-type\-not \f[I]TYPE\f[] ...
Do not search files matching TYPE.
Multiple not\-type flags may be provided.
.RS
.RE
.TP
.B \-u, \-\-unrestricted ...
Reduce the level of \[aq]smart\[aq] searching.
A single \-u doesn\[aq]t respect .gitignore (etc.) files.
Two \-u flags will search hidden files and directories.
Three \-u flags will search binary files.
\-uu is equivalent to grep \-r, and \-uuu is equivalent to grep \-a \-r.
.RS
.RE
.TP
.B \-v, \-\-invert\-match
Invert matching.
.RS
.RE
.TP
.B \-w, \-\-word\-regexp
Only show matches surrounded by word boundaries.
This is equivalent to putting \\b before and after the search pattern.
.RS
.RE
.SH LESS COMMON OPTIONS
.TP
.B \-A, \-\-after\-context \f[I]NUM\f[]
Show NUM lines after each match.
.RS
.RE
.TP
.B \-B, \-\-before\-context \f[I]NUM\f[]
Show NUM lines before each match.
.RS
.RE
.TP
.B \-C, \-\-context \f[I]NUM\f[]
Show NUM lines before and after each match.
.RS
.RE
.TP
.B \-\-column
Show column numbers (1 based) in output.
This only shows the column numbers for the first match on each line.
Note that this doesn\[aq]t try to account for Unicode.
One byte is equal to one column.
.RS
.RE
.TP
.B \-\-context\-separator \f[I]ARG\f[]
The string to use when separating non\-continuous context lines.
Escape sequences may be used.
[default: \-\-]
.RS
.RE
.TP
.B \-\-debug
Show debug messages.
.RS
.RE
.TP
.B \-\-files
Print each file that would be searched (but don\[aq]t search).
.RS
.RE
.TP
.B \-l, \-\-files\-with\-matches
Only show path of each file with matches.
.RS
.RE
.TP
.B \-H, \-\-with\-filename
Prefix each match with the file name that contains it.
This is the default when more than one file is searched.
.RS
.RE
.TP
.B \-\-no\-filename
Never show the filename for a match.
This is the default when one file is searched.
.RS
.RE
.TP
.B \-\-heading
Show the file name above clusters of matches from each file.
This is the default mode at a tty.
.RS
.RE
.TP
.B \-\-no\-heading
Don\[aq]t show any file name heading.
.RS
.RE
.TP
.B \-\-hidden
Search hidden directories and files.
(Hidden directories and files are skipped by default.)
.RS
.RE
.TP
.B \-L, \-\-follow
Follow symlinks.
.RS
.RE
.TP
.B \-\-maxdepth \f[I]NUM\f[]
Descend at most NUM directories below the command line arguments.
A value of zero searches only the starting\-points themselves.
.RS
.RE
.TP
.B \-\-mmap
Search using memory maps when possible.
This is enabled by default when ripgrep thinks it will be faster.
(Note that mmap searching doesn\[aq]t currently support the various
context related options.)
.RS
.RE
.TP
.B \-\-no\-mmap
Never use memory maps, even when they might be faster.
.RS
.RE
.TP
.B \-\-no\-ignore
Don\[aq]t respect ignore files (.gitignore, .ignore, etc.) This implies
\-\-no\-ignore\-parent.
.RS
.RE
.TP
.B \-\-no\-ignore\-parent
Don\[aq]t respect ignore files in parent directories.
.RS
.RE
.TP
.B \-\-no\-ignore\-vcs
Don\[aq]t respect version control ignore files (e.g., .gitignore).
Note that .ignore files will continue to be respected.
.RS
.RE
.TP
.B \-\-null
Whenever a file name is printed, follow it with a NUL byte.
This includes printing filenames before matches, and when printing a
list of matching files such as with \-\-count, \-\-files\-with\-matches
and \-\-files.
.RS
.RE
.TP
.B \-p, \-\-pretty
Alias for \-\-color=always \-\-heading \-n.
.RS
.RE
.TP
.B \-r, \-\-replace \f[I]ARG\f[]
Replace every match with the string given when printing search results.
Neither this flag nor any other flag will modify your files.
.RS
.PP
Capture group indices (e.g., $5) and names (e.g., $foo) are supported in
the replacement string.
.RE
.TP
.B \-s, \-\-case\-sensitive
Search case sensitively.
This overrides \-\-ignore\-case and \-\-smart\-case.
.RS
.RE
.TP
.B \-S, \-\-smart\-case
Search case insensitively if the pattern is all lowercase.
Search case sensitively otherwise.
This is overridden by either \-\-case\-sensitive or \-\-ignore\-case.
.RS
.RE
.TP
.B \-j, \-\-threads \f[I]ARG\f[]
The number of threads to use.
0 means use the number of logical CPUs (capped at 6).
[default: 0]
.RS
.RE
.TP
.B \-\-version
Show the version number of ripgrep and exit.
.RS
.RE
.TP
.B \-\-vimgrep
Show results with every match on its own line, including line numbers
and column numbers.
(With this option, a line with more than one match of the regex will be
printed more than once.)
.RS
.RE
.SH FILE TYPE MANAGEMENT OPTIONS
.TP
.B \-\-type\-list
Show all supported file types and their associated globs.
.RS
.RE
.TP
.B \-\-type\-add \f[I]ARG\f[] ...
Add a new glob for a particular file type.
Only one glob can be added at a time.
Multiple \-\-type\-add flags can be provided.
Unless \-\-type\-clear is used, globs are added to any existing globs
inside of ripgrep.
Note that this must be passed to every invocation of rg.
Type settings are NOT persisted.
.RS
.PP
Example:
\f[C]rg\ \-\-type\-add\ \[aq]foo:*.foo\[aq]\ \-tfoo\ PATTERN\f[]
.RE
.TP
.B \-\-type\-clear \f[I]TYPE\f[] ...
Clear the file type globs previously defined for TYPE.
This only clears the default type definitions that are found inside of
ripgrep.
Note that this must be passed to every invocation of rg.
.RS
.RE

211
doc/rg.1.md Normal file
View File

@@ -0,0 +1,211 @@
# NAME
rg - recursively search current directory for lines matching a pattern
# SYNOPSIS
rg [*options*] -e PATTERN ... [*<*path*> ...*]
rg [*options*] <*pattern*> [*<*path*> ...*]
rg [*options*] --files [*<*path*> ...*]
rg [*options*] --type-list
rg [*options*] --help
rg [*options*] --version
# DESCRIPTION
rg (ripgrep) combines the usability of The Silver Searcher (an ack clone) with
the raw speed of grep.
# COMMON OPTIONS
-a, --text
: Search binary files as if they were text.
-c, --count
: Only show count of line matches for each file.
--color *WHEN*
: Whether to use coloring in match. Valid values are never, always or auto.
[default: auto]
-e, --regexp *PATTERN* ...
: Use PATTERN to search. This option can be provided multiple times, where all
patterns given are searched.
-F, --fixed-strings
: Treat the pattern as a literal string instead of a regular expression.
-g, --glob *GLOB* ...
: Include or exclude files for searching that match the given glob. This always
overrides any other ignore logic. Multiple glob flags may be used. Globbing
rules match .gitignore globs. Precede a glob with a '!' to exclude it.
-h, --help
: Show this usage message.
-i, --ignore-case
: Case insensitive search. Overridden by --case-sensitive.
-n, --line-number
: Show line numbers (1-based). This is enabled by default at a tty.
-N, --no-line-number
: Suppress line numbers.
-q, --quiet
: Do not print anything to stdout. If a match is found in a file, stop
searching that file.
-t, --type *TYPE* ...
: Only search files matching TYPE. Multiple type flags may be provided. Use the
--type-list flag to list all available types.
-T, --type-not *TYPE* ...
: Do not search files matching TYPE. Multiple not-type flags may be provided.
-u, --unrestricted ...
: Reduce the level of 'smart' searching. A single -u doesn't respect .gitignore
(etc.) files. Two -u flags will search hidden files and directories. Three
-u flags will search binary files. -uu is equivalent to grep -r, and -uuu is
equivalent to grep -a -r.
-v, --invert-match
: Invert matching.
-w, --word-regexp
: Only show matches surrounded by word boundaries. This is equivalent to
putting \\b before and after the search pattern.
# LESS COMMON OPTIONS
-A, --after-context *NUM*
: Show NUM lines after each match.
-B, --before-context *NUM*
: Show NUM lines before each match.
-C, --context *NUM*
: Show NUM lines before and after each match.
--column
: Show column numbers (1 based) in output. This only shows the column
numbers for the first match on each line. Note that this doesn't try
to account for Unicode. One byte is equal to one column.
--context-separator *ARG*
: The string to use when separating non-continuous context lines. Escape
sequences may be used. [default: --]
--debug
: Show debug messages.
--files
: Print each file that would be searched (but don't search).
-l, --files-with-matches
: Only show path of each file with matches.
-H, --with-filename
: Prefix each match with the file name that contains it. This is the
default when more than one file is searched.
--no-filename
: Never show the filename for a match. This is the default when
one file is searched.
--heading
: Show the file name above clusters of matches from each file.
This is the default mode at a tty.
--no-heading
: Don't show any file name heading.
--hidden
: Search hidden directories and files. (Hidden directories and files are
skipped by default.)
-L, --follow
: Follow symlinks.
--maxdepth *NUM*
: Descend at most NUM directories below the command line arguments.
A value of zero searches only the starting-points themselves.
--mmap
: Search using memory maps when possible. This is enabled by default
when ripgrep thinks it will be faster. (Note that mmap searching
doesn't currently support the various context related options.)
--no-mmap
: Never use memory maps, even when they might be faster.
--no-ignore
: Don't respect ignore files (.gitignore, .ignore, etc.)
This implies --no-ignore-parent.
--no-ignore-parent
: Don't respect ignore files in parent directories.
--no-ignore-vcs
: Don't respect version control ignore files (e.g., .gitignore).
Note that .ignore files will continue to be respected.
--null
: Whenever a file name is printed, follow it with a NUL byte.
This includes printing filenames before matches, and when printing
a list of matching files such as with --count, --files-with-matches
and --files.
-p, --pretty
: Alias for --color=always --heading -n.
-r, --replace *ARG*
: Replace every match with the string given when printing search results.
Neither this flag nor any other flag will modify your files.
Capture group indices (e.g., $5) and names (e.g., $foo) are supported
in the replacement string.
-s, --case-sensitive
: Search case sensitively. This overrides --ignore-case and --smart-case.
-S, --smart-case
: Search case insensitively if the pattern is all lowercase.
Search case sensitively otherwise. This is overridden by either
--case-sensitive or --ignore-case.
-j, --threads *ARG*
: The number of threads to use. 0 means use the number of logical CPUs
(capped at 6). [default: 0]
--version
: Show the version number of ripgrep and exit.
--vimgrep
: Show results with every match on its own line, including line
numbers and column numbers. (With this option, a line with more
than one match of the regex will be printed more than once.)
# FILE TYPE MANAGEMENT OPTIONS
--type-list
: Show all supported file types and their associated globs.
--type-add *ARG* ...
: Add a new glob for a particular file type. Only one glob can be added
at a time. Multiple --type-add flags can be provided. Unless --type-clear
is used, globs are added to any existing globs inside of ripgrep. Note that
this must be passed to every invocation of rg. Type settings are NOT
persisted.
Example: `rg --type-add 'foo:*.foo' -tfoo PATTERN`
--type-clear *TYPE* ...
: Clear the file type globs previously defined for TYPE. This only clears
the default type definitions that are found inside of ripgrep. Note
that this must be passed to every invocation of rg.

30
globset/Cargo.toml Normal file
View File

@@ -0,0 +1,30 @@
[package]
name = "globset"
version = "0.1.0" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Cross platform single glob and glob set matching. Glob set matching is the
process of matching one or more glob patterns against a single candidate path
simultaneously, and returning all of the globs that matched.
"""
documentation = "https://docs.rs/globset"
homepage = "https://github.com/BurntSushi/ripgrep/tree/master/globset"
repository = "https://github.com/BurntSushi/ripgrep/tree/master/globset"
readme = "README.md"
keywords = ["regex", "glob", "multiple", "set", "pattern"]
license = "Unlicense/MIT"
[lib]
name = "globset"
bench = false
[dependencies]
aho-corasick = "0.5.3"
fnv = "1.0"
lazy_static = "0.2"
log = "0.3"
memchr = "0.1"
regex = "0.1.77"
[dev-dependencies]
glob = "0.2"

122
globset/README.md Normal file
View File

@@ -0,0 +1,122 @@
globset
=======
Cross platform single glob and glob set matching. Glob set matching is the
process of matching one or more glob patterns against a single candidate path
simultaneously, and returning all of the globs that matched.
[![Linux build status](https://api.travis-ci.org/BurntSushi/ripgrep.png)](https://travis-ci.org/BurntSushi/ripgrep)
[![Windows build status](https://ci.appveyor.com/api/projects/status/github/BurntSushi/ripgrep?svg=true)](https://ci.appveyor.com/project/BurntSushi/ripgrep)
[![](https://img.shields.io/crates/v/globset.svg)](https://crates.io/crates/globset)
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
### Documentation
[https://docs.rs/globset](https://docs.rs/globset)
### Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
globset = "0.1"
```
and this to your crate root:
```rust
extern crate globset;
```
### Example: one glob
This example shows how to match a single glob against a single file path.
```rust
use globset::Glob;
let glob = try!(Glob::new("*.rs")).compile_matcher();
assert!(glob.is_match("foo.rs"));
assert!(glob.is_match("foo/bar.rs"));
assert!(!glob.is_match("Cargo.toml"));
```
### Example: configuring a glob matcher
This example shows how to use a `GlobBuilder` to configure aspects of match
semantics. In this example, we prevent wildcards from matching path separators.
```rust
use globset::GlobBuilder;
let glob = try!(GlobBuilder::new("*.rs")
.literal_separator(true).build()).compile_matcher();
assert!(glob.is_match("foo.rs"));
assert!(!glob.is_match("foo/bar.rs")); // no longer matches
assert!(!glob.is_match("Cargo.toml"));
```
### Example: match multiple globs at once
This example shows how to match multiple glob patterns at once.
```rust
use globset::{Glob, GlobSetBuilder};
let mut builder = GlobSetBuilder::new();
// A GlobBuilder can be used to configure each glob's match semantics
// independently.
builder.add(try!(Glob::new("*.rs")));
builder.add(try!(Glob::new("src/lib.rs")));
builder.add(try!(Glob::new("src/**/foo.rs")));
let set = try!(builder.build());
assert_eq!(set.matches("src/bar/baz/foo.rs"), vec![0, 2]);
```
### Performance
This crate implements globs by converting them to regular expressions, and
executing them with the
[`regex`](https://github.com/rust-lang-nursery/regex)
crate.
For single glob matching, performance of this crate should be roughly on par
with the performance of the
[`glob`](https://github.com/rust-lang-nursery/glob)
crate. (`*_regex` correspond to benchmarks for this library while `*_glob`
correspond to benchmarks for the `glob` library.)
Optimizations in the `regex` crate may propel this library past `glob`,
particularly when matching longer paths.
```
test ext_glob ... bench: 425 ns/iter (+/- 21)
test ext_regex ... bench: 175 ns/iter (+/- 10)
test long_glob ... bench: 182 ns/iter (+/- 11)
test long_regex ... bench: 173 ns/iter (+/- 10)
test short_glob ... bench: 69 ns/iter (+/- 4)
test short_regex ... bench: 83 ns/iter (+/- 2)
```
The primary performance advantage of this crate is when matching multiple
globs against a single path. With the `glob` crate, one must match each glob
synchronously, one after the other. In this crate, many can be matched
simultaneously. For example:
```
test many_short_glob ... bench: 1,063 ns/iter (+/- 47)
test many_short_regex_set ... bench: 186 ns/iter (+/- 11)
```
### Comparison with the [`glob`](https://github.com/rust-lang-nursery/glob) crate
* Supports alternate "or" globs, e.g., `*.{foo,bar}`.
* Can match non-UTF-8 file paths correctly.
* Supports matching multiple globs at once.
* Doesn't provide a recursive directory iterator of matching file paths,
although I believe this crate should grow one eventually.
* Supports case insensitive and require-literal-separator match options, but
**doesn't** support the require-literal-leading-dot option.

View File

@@ -1,37 +1,54 @@
/*!
This module benchmarks the glob implementation. For benchmarks on the ripgrep
tool itself, see the benchsuite directory.
*/
#![feature(test)]
extern crate glob;
extern crate globset;
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate test;
use globset::{Candidate, Glob, GlobMatcher, GlobSet, GlobSetBuilder};
const EXT: &'static str = "some/a/bigger/path/to/the/crazy/needle.txt";
const EXT_PAT: &'static str = "*.txt";
const SHORT: &'static str = "some/needle.txt";
const SHORT_PAT: &'static str = "some/**/needle.txt";
const LONG: &'static str = "some/a/bigger/path/to/the/crazy/needle.txt";
const LONG_PAT: &'static str = "some/**/needle.txt";
#[allow(dead_code, unused_variables)]
#[path = "../src/glob.rs"]
mod reglob;
fn new_glob(pat: &str) -> glob::Pattern {
glob::Pattern::new(pat).unwrap()
}
fn new_reglob(pat: &str) -> reglob::Set {
let mut builder = reglob::SetBuilder::new();
builder.add(pat).unwrap();
fn new_reglob(pat: &str) -> GlobMatcher {
Glob::new(pat).unwrap().compile_matcher()
}
fn new_reglob_many(pats: &[&str]) -> GlobSet {
let mut builder = GlobSetBuilder::new();
for pat in pats {
builder.add(Glob::new(pat).unwrap());
}
builder.build().unwrap()
}
fn new_reglob_many(pats: &[&str]) -> reglob::Set {
let mut builder = reglob::SetBuilder::new();
for pat in pats {
builder.add(pat).unwrap();
}
builder.build().unwrap()
#[bench]
fn ext_glob(b: &mut test::Bencher) {
let pat = new_glob(EXT_PAT);
b.iter(|| assert!(pat.matches(EXT)));
}
#[bench]
fn ext_regex(b: &mut test::Bencher) {
let set = new_reglob(EXT_PAT);
let cand = Candidate::new(EXT);
b.iter(|| assert!(set.is_match_candidate(&cand)));
}
#[bench]
@@ -43,7 +60,8 @@ fn short_glob(b: &mut test::Bencher) {
#[bench]
fn short_regex(b: &mut test::Bencher) {
let set = new_reglob(SHORT_PAT);
b.iter(|| assert!(set.is_match(SHORT)));
let cand = Candidate::new(SHORT);
b.iter(|| assert!(set.is_match_candidate(&cand)));
}
#[bench]
@@ -55,7 +73,8 @@ fn long_glob(b: &mut test::Bencher) {
#[bench]
fn long_regex(b: &mut test::Bencher) {
let set = new_reglob(LONG_PAT);
b.iter(|| assert!(set.is_match(LONG)));
let cand = Candidate::new(LONG);
b.iter(|| assert!(set.is_match_candidate(&cand)));
}
const MANY_SHORT_GLOBS: &'static [&'static str] = &[
@@ -97,26 +116,3 @@ fn many_short_regex_set(b: &mut test::Bencher) {
let set = new_reglob_many(MANY_SHORT_GLOBS);
b.iter(|| assert_eq!(2, set.matches(MANY_SHORT_SEARCH).iter().count()));
}
// This is the fastest on my system (beating many_glob by about 2x). This
// suggests that a RegexSet needs quite a few regexes (or a larger haystack)
// in order for it to scale.
//
// TODO(burntsushi): come up with a benchmark that uses more complex patterns
// or a longer haystack.
#[bench]
fn many_short_regex_pattern(b: &mut test::Bencher) {
let pats: Vec<_> = MANY_SHORT_GLOBS.iter().map(|&s| {
let pat = reglob::Pattern::new(s).unwrap();
regex::Regex::new(&pat.to_regex()).unwrap()
}).collect();
b.iter(|| {
let mut count = 0;
for pat in &pats {
if pat.is_match(MANY_SHORT_SEARCH) {
count += 1;
}
}
assert_eq!(2, count);
})
}

1300
globset/src/glob.rs Normal file

File diff suppressed because it is too large Load Diff

753
globset/src/lib.rs Normal file
View File

@@ -0,0 +1,753 @@
/*!
The globset crate provides cross platform single glob and glob set matching.
Glob set matching is the process of matching one or more glob patterns against
a single candidate path simultaneously, and returning all of the globs that
matched. For example, given this set of globs:
```ignore
*.rs
src/lib.rs
src/**/foo.rs
```
and a path `src/bar/baz/foo.rs`, then the set would report the first and third
globs as matching.
Single glob matching is also provided and is done by converting globs to
# Example: one glob
This example shows how to match a single glob against a single file path.
```
# fn example() -> Result<(), globset::Error> {
use globset::Glob;
let glob = try!(Glob::new("*.rs")).compile_matcher();
assert!(glob.is_match("foo.rs"));
assert!(glob.is_match("foo/bar.rs"));
assert!(!glob.is_match("Cargo.toml"));
# Ok(()) } example().unwrap();
```
# Example: configuring a glob matcher
This example shows how to use a `GlobBuilder` to configure aspects of match
semantics. In this example, we prevent wildcards from matching path separators.
```
# fn example() -> Result<(), globset::Error> {
use globset::GlobBuilder;
let glob = try!(GlobBuilder::new("*.rs")
.literal_separator(true).build()).compile_matcher();
assert!(glob.is_match("foo.rs"));
assert!(!glob.is_match("foo/bar.rs")); // no longer matches
assert!(!glob.is_match("Cargo.toml"));
# Ok(()) } example().unwrap();
```
# Example: match multiple globs at once
This example shows how to match multiple glob patterns at once.
```
# fn example() -> Result<(), globset::Error> {
use globset::{Glob, GlobSetBuilder};
let mut builder = GlobSetBuilder::new();
// A GlobBuilder can be used to configure each glob's match semantics
// independently.
builder.add(try!(Glob::new("*.rs")));
builder.add(try!(Glob::new("src/lib.rs")));
builder.add(try!(Glob::new("src/**/foo.rs")));
let set = try!(builder.build());
assert_eq!(set.matches("src/bar/baz/foo.rs"), vec![0, 2]);
# Ok(()) } example().unwrap();
```
# Syntax
Standard Unix-style glob syntax is supported:
* `?` matches any single character. (If the `literal_separator` option is
enabled, then `?` can never match a path separator.)
* `*` matches zero or more characters. (If the `literal_separator` option is
enabled, then `*` can never match a path separator.)
* `**` recursively matches directories but are only legal in three situations.
First, if the glob starts with <code>\*\*&#x2F;</code>, then it matches
all directories. For example, <code>\*\*&#x2F;foo</code> matches `foo`
and `bar/foo` but not `foo/bar`. Secondly, if the glob ends with
<code>&#x2F;\*\*</code>, then it matches all sub-entries. For example,
<code>foo&#x2F;\*\*</code> matches `foo/a` and `foo/a/b`, but not `foo`.
Thirdly, if the glob contains <code>&#x2F;\*\*&#x2F;</code> anywhere within
the pattern, then it matches zero or more directories. Using `**` anywhere
else is illegal (N.B. the glob `**` is allowed and means "match everything").
* `{a,b}` matches `a` or `b` where `a` and `b` are arbitrary glob patterns.
(N.B. Nesting `{...}` is not currently allowed.)
* `[ab]` matches `a` or `b` where `a` and `b` are characters. Use
`[!ab]` to match any character except for `a` and `b`.
* Metacharacters such as `*` and `?` can be escaped with character class
notation. e.g., `[*]` matches `*`.
A `GlobBuilder` can be used to prevent wildcards from matching path separators,
or to enable case insensitive matching.
*/
#![deny(missing_docs)]
extern crate aho_corasick;
extern crate fnv;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate memchr;
extern crate regex;
use std::borrow::Cow;
use std::collections::{BTreeMap, HashMap};
use std::error::Error as StdError;
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::hash;
use std::path::Path;
use std::str;
use aho_corasick::{Automaton, AcAutomaton, FullAcAutomaton};
use regex::bytes::{Regex, RegexBuilder, RegexSet};
use pathutil::{
file_name, file_name_ext, normalize_path, os_str_bytes, path_bytes,
};
use glob::MatchStrategy;
pub use glob::{Glob, GlobBuilder, GlobMatcher};
mod glob;
mod pathutil;
macro_rules! eprintln {
($($tt:tt)*) => {{
use std::io::Write;
let _ = writeln!(&mut ::std::io::stderr(), $($tt)*);
}}
}
/// Represents an error that can occur when parsing a glob pattern.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Error {
/// Occurs when a use of `**` is invalid. Namely, `**` can only appear
/// adjacent to a path separator, or the beginning/end of a glob.
InvalidRecursive,
/// Occurs when a character class (e.g., `[abc]`) is not closed.
UnclosedClass,
/// Occurs when a range in a character (e.g., `[a-z]`) is invalid. For
/// example, if the range starts with a lexicographically larger character
/// than it ends with.
InvalidRange(char, char),
/// Occurs when a `}` is found without a matching `{`.
UnopenedAlternates,
/// Occurs when a `{` is found without a matching `}`.
UnclosedAlternates,
/// Occurs when an alternating group is nested inside another alternating
/// group, e.g., `{{a,b},{c,d}}`.
NestedAlternates,
/// An error associated with parsing or compiling a regex.
Regex(String),
}
impl StdError for Error {
fn description(&self) -> &str {
match *self {
Error::InvalidRecursive => {
"invalid use of **; must be one path component"
}
Error::UnclosedClass => {
"unclosed character class; missing ']'"
}
Error::InvalidRange(_, _) => {
"invalid character range"
}
Error::UnopenedAlternates => {
"unopened alternate group; missing '{' \
(maybe escape '}' with '[}]'?)"
}
Error::UnclosedAlternates => {
"unclosed alternate group; missing '}' \
(maybe escape '{' with '[{]'?)"
}
Error::NestedAlternates => {
"nested alternate groups are not allowed"
}
Error::Regex(ref err) => err,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::InvalidRecursive
| Error::UnclosedClass
| Error::UnopenedAlternates
| Error::UnclosedAlternates
| Error::NestedAlternates
| Error::Regex(_) => {
write!(f, "{}", self.description())
}
Error::InvalidRange(s, e) => {
write!(f, "invalid range; '{}' > '{}'", s, e)
}
}
}
}
fn new_regex(pat: &str) -> Result<Regex, Error> {
RegexBuilder::new(pat)
.dot_matches_new_line(true)
.size_limit(10 * (1 << 20))
.dfa_size_limit(10 * (1 << 20))
.compile()
.map_err(|err| Error::Regex(err.to_string()))
}
fn new_regex_set<I, S>(pats: I) -> Result<RegexSet, Error>
where S: AsRef<str>, I: IntoIterator<Item=S> {
RegexSet::new(pats).map_err(|err| Error::Regex(err.to_string()))
}
type Fnv = hash::BuildHasherDefault<fnv::FnvHasher>;
/// GlobSet represents a group of globs that can be matched together in a
/// single pass.
#[derive(Clone, Debug)]
pub struct GlobSet {
strats: Vec<GlobSetMatchStrategy>,
}
impl GlobSet {
/// Returns true if any glob in this set matches the path given.
pub fn is_match<P: AsRef<Path>>(&self, path: P) -> bool {
self.is_match_candidate(&Candidate::new(path.as_ref()))
}
/// Returns true if any glob in this set matches the path given.
///
/// This takes a Candidate as input, which can be used to amortize the
/// cost of preparing a path for matching.
pub fn is_match_candidate(&self, path: &Candidate) -> bool {
for strat in &self.strats {
if strat.is_match(path) {
return true;
}
}
false
}
/// Returns the sequence number of every glob pattern that matches the
/// given path.
///
/// This takes a Candidate as input, which can be used to amortize the
/// cost of preparing a path for matching.
pub fn matches<P: AsRef<Path>>(&self, path: P) -> Vec<usize> {
self.matches_candidate(&Candidate::new(path.as_ref()))
}
/// Returns the sequence number of every glob pattern that matches the
/// given path.
///
/// This takes a Candidate as input, which can be used to amortize the
/// cost of preparing a path for matching.
pub fn matches_candidate(&self, path: &Candidate) -> Vec<usize> {
let mut into = vec![];
self.matches_candidate_into(path, &mut into);
into
}
/// Adds the sequence number of every glob pattern that matches the given
/// path to the vec given.
///
/// `into` is is cleared before matching begins, and contains the set of
/// sequence numbers (in ascending order) after matching ends. If no globs
/// were matched, then `into` will be empty.
pub fn matches_candidate_into(
&self,
path: &Candidate,
into: &mut Vec<usize>,
) {
into.clear();
for strat in &self.strats {
strat.matches_into(path, into);
}
into.sort();
into.dedup();
}
fn new(pats: &[Glob]) -> Result<GlobSet, Error> {
let mut lits = LiteralStrategy::new();
let mut base_lits = BasenameLiteralStrategy::new();
let mut exts = ExtensionStrategy::new();
let mut prefixes = MultiStrategyBuilder::new();
let mut suffixes = MultiStrategyBuilder::new();
let mut required_exts = RequiredExtensionStrategyBuilder::new();
let mut regexes = MultiStrategyBuilder::new();
for (i, p) in pats.iter().enumerate() {
match MatchStrategy::new(p) {
MatchStrategy::Literal(lit) => {
lits.add(i, lit);
}
MatchStrategy::BasenameLiteral(lit) => {
base_lits.add(i, lit);
}
MatchStrategy::Extension(ext) => {
exts.add(i, ext);
}
MatchStrategy::Prefix(prefix) => {
prefixes.add(i, prefix);
}
MatchStrategy::Suffix { suffix, component } => {
if component {
lits.add(i, suffix[1..].to_string());
}
suffixes.add(i, suffix);
}
MatchStrategy::RequiredExtension(ext) => {
required_exts.add(i, ext, p.regex().to_owned());
}
MatchStrategy::Regex => {
debug!("glob converted to regex: {:?}", p);
regexes.add(i, p.regex().to_owned());
}
}
}
debug!("built glob set; {} literals, {} basenames, {} extensions, \
{} prefixes, {} suffixes, {} required extensions, {} regexes",
lits.0.len(), base_lits.0.len(), exts.0.len(),
prefixes.literals.len(), suffixes.literals.len(),
required_exts.0.len(), regexes.literals.len());
Ok(GlobSet {
strats: vec![
GlobSetMatchStrategy::Extension(exts),
GlobSetMatchStrategy::BasenameLiteral(base_lits),
GlobSetMatchStrategy::Literal(lits),
GlobSetMatchStrategy::Suffix(suffixes.suffix()),
GlobSetMatchStrategy::Prefix(prefixes.prefix()),
GlobSetMatchStrategy::RequiredExtension(
try!(required_exts.build())),
GlobSetMatchStrategy::Regex(try!(regexes.regex_set())),
],
})
}
}
/// GlobSetBuilder builds a group of patterns that can be used to
/// simultaneously match a file path.
pub struct GlobSetBuilder {
pats: Vec<Glob>,
}
impl GlobSetBuilder {
/// Create a new GlobSetBuilder. A GlobSetBuilder can be used to add new
/// patterns. Once all patterns have been added, `build` should be called
/// to produce a `GlobSet`, which can then be used for matching.
pub fn new() -> GlobSetBuilder {
GlobSetBuilder { pats: vec![] }
}
/// Builds a new matcher from all of the glob patterns added so far.
///
/// Once a matcher is built, no new patterns can be added to it.
pub fn build(&self) -> Result<GlobSet, Error> {
GlobSet::new(&self.pats)
}
/// Add a new pattern to this set.
#[allow(dead_code)]
pub fn add(&mut self, pat: Glob) -> &mut GlobSetBuilder {
self.pats.push(pat);
self
}
}
/// A candidate path for matching.
///
/// All glob matching in this crate operates on `Candidate` values.
/// Constructing candidates has a very small cost associated with it, so
/// callers may find it beneficial to amortize that cost when matching a single
/// path against multiple globs or sets of globs.
#[derive(Clone, Debug)]
pub struct Candidate<'a> {
path: Cow<'a, [u8]>,
basename: Cow<'a, [u8]>,
ext: &'a OsStr,
}
impl<'a> Candidate<'a> {
/// Create a new candidate for matching from the given path.
pub fn new<P: AsRef<Path> + ?Sized>(path: &'a P) -> Candidate<'a> {
let path = path.as_ref();
let basename = file_name(path).unwrap_or(OsStr::new(""));
Candidate {
path: normalize_path(path_bytes(path)),
basename: os_str_bytes(basename),
ext: file_name_ext(basename).unwrap_or(OsStr::new("")),
}
}
fn path_prefix(&self, max: usize) -> &[u8] {
if self.path.len() <= max {
&*self.path
} else {
&self.path[..max]
}
}
fn path_suffix(&self, max: usize) -> &[u8] {
if self.path.len() <= max {
&*self.path
} else {
&self.path[self.path.len() - max..]
}
}
}
#[derive(Clone, Debug)]
enum GlobSetMatchStrategy {
Literal(LiteralStrategy),
BasenameLiteral(BasenameLiteralStrategy),
Extension(ExtensionStrategy),
Prefix(PrefixStrategy),
Suffix(SuffixStrategy),
RequiredExtension(RequiredExtensionStrategy),
Regex(RegexSetStrategy),
}
impl GlobSetMatchStrategy {
fn is_match(&self, candidate: &Candidate) -> bool {
use self::GlobSetMatchStrategy::*;
match *self {
Literal(ref s) => s.is_match(candidate),
BasenameLiteral(ref s) => s.is_match(candidate),
Extension(ref s) => s.is_match(candidate),
Prefix(ref s) => s.is_match(candidate),
Suffix(ref s) => s.is_match(candidate),
RequiredExtension(ref s) => s.is_match(candidate),
Regex(ref s) => s.is_match(candidate),
}
}
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
use self::GlobSetMatchStrategy::*;
match *self {
Literal(ref s) => s.matches_into(candidate, matches),
BasenameLiteral(ref s) => s.matches_into(candidate, matches),
Extension(ref s) => s.matches_into(candidate, matches),
Prefix(ref s) => s.matches_into(candidate, matches),
Suffix(ref s) => s.matches_into(candidate, matches),
RequiredExtension(ref s) => s.matches_into(candidate, matches),
Regex(ref s) => s.matches_into(candidate, matches),
}
}
}
#[derive(Clone, Debug)]
struct LiteralStrategy(BTreeMap<Vec<u8>, Vec<usize>>);
impl LiteralStrategy {
fn new() -> LiteralStrategy {
LiteralStrategy(BTreeMap::new())
}
fn add(&mut self, global_index: usize, lit: String) {
self.0.entry(lit.into_bytes()).or_insert(vec![]).push(global_index);
}
fn is_match(&self, candidate: &Candidate) -> bool {
self.0.contains_key(&*candidate.path)
}
#[inline(never)]
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
if let Some(hits) = self.0.get(&*candidate.path) {
matches.extend(hits);
}
}
}
#[derive(Clone, Debug)]
struct BasenameLiteralStrategy(BTreeMap<Vec<u8>, Vec<usize>>);
impl BasenameLiteralStrategy {
fn new() -> BasenameLiteralStrategy {
BasenameLiteralStrategy(BTreeMap::new())
}
fn add(&mut self, global_index: usize, lit: String) {
self.0.entry(lit.into_bytes()).or_insert(vec![]).push(global_index);
}
fn is_match(&self, candidate: &Candidate) -> bool {
if candidate.basename.is_empty() {
return false;
}
self.0.contains_key(&*candidate.basename)
}
#[inline(never)]
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
if candidate.basename.is_empty() {
return;
}
if let Some(hits) = self.0.get(&*candidate.basename) {
matches.extend(hits);
}
}
}
#[derive(Clone, Debug)]
struct ExtensionStrategy(HashMap<OsString, Vec<usize>, Fnv>);
impl ExtensionStrategy {
fn new() -> ExtensionStrategy {
ExtensionStrategy(HashMap::with_hasher(Fnv::default()))
}
fn add(&mut self, global_index: usize, ext: OsString) {
self.0.entry(ext).or_insert(vec![]).push(global_index);
}
fn is_match(&self, candidate: &Candidate) -> bool {
if candidate.ext.is_empty() {
return false;
}
self.0.contains_key(candidate.ext)
}
#[inline(never)]
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
if candidate.ext.is_empty() {
return;
}
if let Some(hits) = self.0.get(candidate.ext) {
matches.extend(hits);
}
}
}
#[derive(Clone, Debug)]
struct PrefixStrategy {
matcher: FullAcAutomaton<Vec<u8>>,
map: Vec<usize>,
longest: usize,
}
impl PrefixStrategy {
fn is_match(&self, candidate: &Candidate) -> bool {
let path = candidate.path_prefix(self.longest);
for m in self.matcher.find_overlapping(path) {
if m.start == 0 {
return true;
}
}
false
}
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
let path = candidate.path_prefix(self.longest);
for m in self.matcher.find_overlapping(path) {
if m.start == 0 {
matches.push(self.map[m.pati]);
}
}
}
}
#[derive(Clone, Debug)]
struct SuffixStrategy {
matcher: FullAcAutomaton<Vec<u8>>,
map: Vec<usize>,
longest: usize,
}
impl SuffixStrategy {
fn is_match(&self, candidate: &Candidate) -> bool {
let path = candidate.path_suffix(self.longest);
for m in self.matcher.find_overlapping(path) {
if m.end == path.len() {
return true;
}
}
false
}
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
let path = candidate.path_suffix(self.longest);
for m in self.matcher.find_overlapping(path) {
if m.end == path.len() {
matches.push(self.map[m.pati]);
}
}
}
}
#[derive(Clone, Debug)]
struct RequiredExtensionStrategy(HashMap<OsString, Vec<(usize, Regex)>, Fnv>);
impl RequiredExtensionStrategy {
fn is_match(&self, candidate: &Candidate) -> bool {
if candidate.ext.is_empty() {
return false;
}
match self.0.get(candidate.ext) {
None => false,
Some(regexes) => {
for &(_, ref re) in regexes {
if re.is_match(&*candidate.path) {
return true;
}
}
false
}
}
}
#[inline(never)]
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
if candidate.ext.is_empty() {
return;
}
if let Some(regexes) = self.0.get(candidate.ext) {
for &(global_index, ref re) in regexes {
if re.is_match(&*candidate.path) {
matches.push(global_index);
}
}
}
}
}
#[derive(Clone, Debug)]
struct RegexSetStrategy {
matcher: RegexSet,
map: Vec<usize>,
}
impl RegexSetStrategy {
fn is_match(&self, candidate: &Candidate) -> bool {
self.matcher.is_match(&*candidate.path)
}
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
for i in self.matcher.matches(&*candidate.path) {
matches.push(self.map[i]);
}
}
}
#[derive(Clone, Debug)]
struct MultiStrategyBuilder {
literals: Vec<String>,
map: Vec<usize>,
longest: usize,
}
impl MultiStrategyBuilder {
fn new() -> MultiStrategyBuilder {
MultiStrategyBuilder {
literals: vec![],
map: vec![],
longest: 0,
}
}
fn add(&mut self, global_index: usize, literal: String) {
if literal.len() > self.longest {
self.longest = literal.len();
}
self.map.push(global_index);
self.literals.push(literal);
}
fn prefix(self) -> PrefixStrategy {
let it = self.literals.into_iter().map(|s| s.into_bytes());
PrefixStrategy {
matcher: AcAutomaton::new(it).into_full(),
map: self.map,
longest: self.longest,
}
}
fn suffix(self) -> SuffixStrategy {
let it = self.literals.into_iter().map(|s| s.into_bytes());
SuffixStrategy {
matcher: AcAutomaton::new(it).into_full(),
map: self.map,
longest: self.longest,
}
}
fn regex_set(self) -> Result<RegexSetStrategy, Error> {
Ok(RegexSetStrategy {
matcher: try!(new_regex_set(self.literals)),
map: self.map,
})
}
}
#[derive(Clone, Debug)]
struct RequiredExtensionStrategyBuilder(
HashMap<OsString, Vec<(usize, String)>>,
);
impl RequiredExtensionStrategyBuilder {
fn new() -> RequiredExtensionStrategyBuilder {
RequiredExtensionStrategyBuilder(HashMap::new())
}
fn add(&mut self, global_index: usize, ext: OsString, regex: String) {
self.0.entry(ext).or_insert(vec![]).push((global_index, regex));
}
fn build(self) -> Result<RequiredExtensionStrategy, Error> {
let mut exts = HashMap::with_hasher(Fnv::default());
for (ext, regexes) in self.0.into_iter() {
exts.insert(ext.clone(), vec![]);
for (global_index, regex) in regexes {
let compiled = try!(new_regex(&regex));
exts.get_mut(&ext).unwrap().push((global_index, compiled));
}
}
Ok(RequiredExtensionStrategy(exts))
}
}
#[cfg(test)]
mod tests {
use super::GlobSetBuilder;
use glob::Glob;
#[test]
fn set_works() {
let mut builder = GlobSetBuilder::new();
builder.add(Glob::new("src/**/*.rs").unwrap());
builder.add(Glob::new("*.c").unwrap());
builder.add(Glob::new("src/lib.rs").unwrap());
let set = builder.build().unwrap();
assert!(set.is_match("foo.c"));
assert!(set.is_match("src/foo.c"));
assert!(!set.is_match("foo.rs"));
assert!(!set.is_match("tests/foo.rs"));
assert!(set.is_match("src/foo.rs"));
assert!(set.is_match("src/grep/src/main.rs"));
let matches = set.matches("src/lib.rs");
assert_eq!(2, matches.len());
assert_eq!(0, matches[0]);
assert_eq!(2, matches[1]);
}
}

180
globset/src/pathutil.rs Normal file
View File

@@ -0,0 +1,180 @@
use std::borrow::Cow;
use std::ffi::OsStr;
use std::path::Path;
/// The final component of the path, if it is a normal file.
///
/// If the path terminates in ., .., or consists solely of a root of prefix,
/// file_name will return None.
#[cfg(unix)]
pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
path: &'a P,
) -> Option<&'a OsStr> {
use std::os::unix::ffi::OsStrExt;
use memchr::memrchr;
let path = path.as_ref().as_os_str().as_bytes();
if path.is_empty() {
return None;
} else if path.len() == 1 && path[0] == b'.' {
return None;
} else if path.last() == Some(&b'.') {
return None;
} else if path.len() >= 2 && &path[path.len() - 2..] == &b".."[..] {
return None;
}
let last_slash = memrchr(b'/', path).map(|i| i + 1).unwrap_or(0);
Some(OsStr::from_bytes(&path[last_slash..]))
}
/// The final component of the path, if it is a normal file.
///
/// If the path terminates in ., .., or consists solely of a root of prefix,
/// file_name will return None.
#[cfg(not(unix))]
pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
path: &'a P,
) -> Option<&'a OsStr> {
path.as_ref().file_name()
}
/// Return a file extension given a path's file name.
///
/// Note that this does NOT match the semantics of std::path::Path::extension.
/// Namely, the extension includes the `.` and matching is otherwise more
/// liberal. Specifically, the extenion is:
///
/// * None, if the file name given is empty;
/// * None, if there is no embedded `.`;
/// * Otherwise, the portion of the file name starting with the final `.`.
///
/// e.g., A file name of `.rs` has an extension `.rs`.
///
/// N.B. This is done to make certain glob match optimizations easier. Namely,
/// a pattern like `*.rs` is obviously trying to match files with a `rs`
/// extension, but it also matches files like `.rs`, which doesn't have an
/// extension according to std::path::Path::extension.
pub fn file_name_ext(name: &OsStr) -> Option<&OsStr> {
// Yes, these functions are awful, and yes, we are completely violating
// the abstraction barrier of std::ffi. The barrier we're violating is
// that an OsStr's encoding is *ASCII compatible*. While this is obviously
// true on Unix systems, it's also true on Windows because an OsStr uses
// WTF-8 internally: https://simonsapin.github.io/wtf-8/
//
// We should consider doing the same for the other path utility functions.
// Right now, we don't break any barriers, but Windows users are paying
// for it.
//
// Got any better ideas that don't cost anything? Hit me up. ---AG
unsafe fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
::std::mem::transmute(s)
}
unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
::std::mem::transmute(s)
}
if name.is_empty() {
return None;
}
let name = unsafe { os_str_as_u8_slice(name) };
for (i, &b) in name.iter().enumerate().rev() {
if b == b'.' {
return Some(unsafe { u8_slice_as_os_str(&name[i..]) });
}
}
None
}
/// Return raw bytes of a path, transcoded to UTF-8 if necessary.
pub fn path_bytes(path: &Path) -> Cow<[u8]> {
os_str_bytes(path.as_os_str())
}
/// Return the raw bytes of the given OS string, transcoded to UTF-8 if
/// necessary.
#[cfg(unix)]
pub fn os_str_bytes(s: &OsStr) -> Cow<[u8]> {
use std::os::unix::ffi::OsStrExt;
Cow::Borrowed(s.as_bytes())
}
/// Return the raw bytes of the given OS string, transcoded to UTF-8 if
/// necessary.
#[cfg(not(unix))]
pub fn os_str_bytes(s: &OsStr) -> Cow<[u8]> {
// TODO(burntsushi): On Windows, OS strings are WTF-8, which is a superset
// of UTF-8, so even if we could get at the raw bytes, they wouldn't
// be useful. We *must* convert to UTF-8 before doing path matching.
// Unfortunate, but necessary.
match s.to_string_lossy() {
Cow::Owned(s) => Cow::Owned(s.into_bytes()),
Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
}
}
/// Normalizes a path to use `/` as a separator everywhere, even on platforms
/// that recognize other characters as separators.
#[cfg(unix)]
pub fn normalize_path(path: Cow<[u8]>) -> Cow<[u8]> {
// UNIX only uses /, so we're good.
path
}
/// Normalizes a path to use `/` as a separator everywhere, even on platforms
/// that recognize other characters as separators.
#[cfg(not(unix))]
pub fn normalize_path(mut path: Cow<[u8]>) -> Cow<[u8]> {
use std::path::is_separator;
for i in 0..path.len() {
if path[i] == b'/' || !is_separator(path[i] as char) {
continue;
}
path.to_mut()[i] = b'/';
}
path
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use std::ffi::OsStr;
use super::{file_name_ext, normalize_path};
macro_rules! ext {
($name:ident, $file_name:expr, $ext:expr) => {
#[test]
fn $name() {
let got = file_name_ext(OsStr::new($file_name));
assert_eq!($ext.map(OsStr::new), got);
}
};
}
ext!(ext1, "foo.rs", Some(".rs"));
ext!(ext2, ".rs", Some(".rs"));
ext!(ext3, "..rs", Some(".rs"));
ext!(ext4, "", None::<&str>);
ext!(ext5, "foo", None::<&str>);
macro_rules! normalize {
($name:ident, $path:expr, $expected:expr) => {
#[test]
fn $name() {
let got = normalize_path(Cow::Owned($path.to_vec()));
assert_eq!($expected.to_vec(), got.into_owned());
}
};
}
normalize!(normal1, b"foo", b"foo");
normalize!(normal2, b"foo/bar", b"foo/bar");
#[cfg(unix)]
normalize!(normal3, b"foo\\bar", b"foo\\bar");
#[cfg(not(unix))]
normalize!(normal3, b"foo\\bar", b"foo/bar");
#[cfg(unix)]
normalize!(normal4, b"foo\\bar/baz", b"foo\\bar/baz");
#[cfg(not(unix))]
normalize!(normal4, b"foo\\bar/baz", b"foo/bar/baz");
}

View File

@@ -1,20 +1,20 @@
[package]
publish = false
name = "grep"
version = "0.1.0" #:version
version = "0.1.3" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Fast line oriented regex searching as a library.
"""
documentation = "https://github.com/BurntSushi/xrep"
homepage = "https://github.com/BurntSushi/xrep"
repository = "https://github.com/BurntSushi/xrep"
documentation = "http://burntsushi.net/rustdoc/grep/"
homepage = "https://github.com/BurntSushi/ripgrep"
repository = "https://github.com/BurntSushi/ripgrep"
readme = "README.md"
keywords = ["regex", "grep", "egrep", "search", "pattern"]
license = "Unlicense/MIT"
[dependencies]
log = "0.3"
memchr = "0.1"
memmap = "0.2"
regex = "0.1.75"
regex = "0.1.77"
regex-syntax = "0.3.5"

4
grep/README.md Normal file
View File

@@ -0,0 +1,4 @@
grep
----
This is a *library* that provides grep-style line-by-line regex searching (with
comparable performance to `grep` itself).

View File

@@ -4,6 +4,8 @@
A fast line oriented regex searcher.
*/
#[macro_use]
extern crate log;
extern crate memchr;
extern crate regex;
extern crate regex_syntax as syntax;
@@ -17,6 +19,7 @@ pub use search::{Grep, GrepBuilder, Iter, Match};
mod literals;
mod nonl;
mod search;
mod word_boundary;
/// Result is a convenient type alias that fixes the type of the error to
/// the `Error` type defined in this crate.
@@ -60,7 +63,7 @@ impl fmt::Display for Error {
match *self {
Error::Regex(ref err) => err.fmt(f),
Error::LiteralNotAllowed(chr) => {
write!(f, "Literal '{}' not allowed.", chr)
write!(f, "Literal {:?} not allowed.", chr)
}
Error::__Nonexhaustive => unreachable!(),
}

View File

@@ -1,13 +1,21 @@
/*!
The literals module is responsible for extracting *inner* literals out of the
AST of a regular expression. Normally this is the job of the regex engine
itself, but the regex engine doesn't look for inner literals. Since we're doing
line based searching, we can use them, so we need to do it ourselves.
Note that this implementation is incredibly suspicious. We need something more
principled.
*/
use std::cmp;
use std::iter;
use regex::bytes::Regex;
use syntax::{
Expr, Literals, Lit,
Repeater,
ByteClass, ByteRange, CharClass, ClassRange, Repeater,
};
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct LiteralSets {
prefixes: Literals,
suffixes: Literals,
@@ -27,6 +35,7 @@ impl LiteralSets {
pub fn to_regex(&self) -> Option<Regex> {
if self.prefixes.all_complete() && !self.prefixes.is_empty() {
debug!("literal prefixes detected: {:?}", self.prefixes);
// When this is true, the regex engine will do a literal scan.
return None;
}
@@ -56,13 +65,27 @@ impl LiteralSets {
if suf_lcs.len() > lit.len() {
lit = suf_lcs;
}
if req.len() > lit.len() {
if req_lits.len() == 1 && req.len() > lit.len() {
lit = req;
}
if lit.is_empty() {
// Special case: if we detected an alternation of inner required
// literals and its longest literal is bigger than the longest
// prefix/suffix, then choose the alternation. In practice, this
// helps with case insensitive matching, which can generate lots of
// inner required literals.
let any_empty = req_lits.iter().any(|lit| lit.is_empty());
if req.len() > lit.len() && req_lits.len() > 1 && !any_empty {
debug!("required literals found: {:?}", req_lits);
let alts: Vec<String> =
req_lits.into_iter().map(|x| bytes_to_regex(x)).collect();
// Literals always compile.
Some(Regex::new(&alts.join("|")).unwrap())
} else if lit.is_empty() {
None
} else {
// Literals always compile.
debug!("required literal found: {:?}", show(lit));
Some(Regex::new(&bytes_to_regex(lit)).unwrap())
}
}
@@ -75,14 +98,30 @@ fn union_required(expr: &Expr, lits: &mut Literals) {
let s: String = chars.iter().cloned().collect();
lits.cross_add(s.as_bytes());
}
Literal { casei: true, .. } => {
lits.cut();
Literal { ref chars, casei: true } => {
for &c in chars {
let cls = CharClass::new(vec![
ClassRange { start: c, end: c },
]).case_fold();
if !lits.add_char_class(&cls) {
lits.cut();
return;
}
}
}
LiteralBytes { ref bytes, casei: false } => {
lits.cross_add(bytes);
}
LiteralBytes { casei: true, .. } => {
lits.cut();
LiteralBytes { ref bytes, casei: true } => {
for &b in bytes {
let cls = ByteClass::new(vec![
ByteRange { start: b, end: b },
]).case_fold();
if !lits.add_byte_class(&cls) {
lits.cut();
return;
}
}
}
Class(_) => {
lits.cut();
@@ -141,8 +180,6 @@ fn repeat_range_literals<F: FnMut(&Expr, &mut Literals)>(
lits: &mut Literals,
mut f: F,
) {
use syntax::Expr::*;
if min == 0 {
// This is a bit conservative. If `max` is set, then we could
// treat this as a finite set of alternations. For now, we
@@ -150,8 +187,12 @@ fn repeat_range_literals<F: FnMut(&Expr, &mut Literals)>(
lits.cut();
} else {
let n = cmp::min(lits.limit_size(), min as usize);
let es = iter::repeat(e.clone()).take(n).collect();
f(&Concat(es), lits);
// We only extract literals from a single repetition, even though
// we could do more. e.g., `a{3}` will have `a` extracted instead of
// `aaa`. The reason is that inner literal extraction can't be unioned
// across repetitions. e.g., extracting `foofoofoo` from `(\w+foo){3}`
// is wrong.
f(e, lits);
if n < min as usize {
lits.cut();
}
@@ -205,3 +246,18 @@ fn bytes_to_regex(bs: &[u8]) -> String {
}
s
}
/// Converts arbitrary bytes to a nice string.
fn show(bs: &[u8]) -> String {
// Why aren't we using this to feed to the regex? Doesn't really matter
// I guess. ---AG
use std::ascii::escape_default;
use std::str;
let mut nice = String::new();
for &b in bs {
let part: Vec<u8> = escape_default(b).collect();
nice.push_str(str::from_utf8(&part).unwrap());
}
nice
}

View File

@@ -10,6 +10,10 @@ use {Error, Result};
/// If `byte` is not an ASCII character (i.e., greater than `0x7F`), then this
/// function panics.
pub fn remove(expr: Expr, byte: u8) -> Result<Expr> {
// TODO(burntsushi): There is a bug in this routine where only `\n` is
// handled correctly. Namely, `AnyChar` and `AnyByte` need to be translated
// to proper character classes instead of the special `AnyCharNoNL` and
// `AnyByteNoNL` classes.
use syntax::Expr::*;
assert!(byte <= 0x7F);
let chr = byte as char;

View File

@@ -4,6 +4,8 @@ use syntax;
use literals::LiteralSets;
use nonl;
use syntax::Expr;
use word_boundary::strip_unicode_word_boundaries;
use Result;
/// A matched line.
@@ -50,6 +52,7 @@ pub struct GrepBuilder {
#[derive(Clone, Debug)]
struct Options {
case_insensitive: bool,
case_smart: bool,
line_terminator: u8,
size_limit: usize,
dfa_size_limit: usize,
@@ -59,6 +62,7 @@ impl Default for Options {
fn default() -> Options {
Options {
case_insensitive: false,
case_smart: false,
line_terminator: b'\n',
size_limit: 10 * (1 << 20),
dfa_size_limit: 10 * (1 << 20),
@@ -96,6 +100,18 @@ impl GrepBuilder {
self
}
/// Whether to enable smart case search or not (disabled by default).
///
/// Smart case uses case insensitive search if the regex is contains all
/// lowercase literal characters. Otherwise, a case sensitive search is
/// used instead.
///
/// Enabling the case_insensitive flag overrides this.
pub fn case_smart(mut self, yes: bool) -> GrepBuilder {
self.opts.case_smart = yes;
self
}
/// Set the approximate size limit of the compiled regular expression.
///
/// This roughly corresponds to the number of bytes occupied by a
@@ -127,22 +143,38 @@ impl GrepBuilder {
pub fn build(self) -> Result<Grep> {
let expr = try!(self.parse());
let literals = LiteralSets::create(&expr);
let re = try!(
RegexBuilder::new(&expr.to_string())
.case_insensitive(self.opts.case_insensitive)
.multi_line(true)
.unicode(true)
.size_limit(self.opts.size_limit)
.dfa_size_limit(self.opts.dfa_size_limit)
.compile()
);
let re = try!(self.regex(&expr));
let required = literals.to_regex().or_else(|| {
let expr = match strip_unicode_word_boundaries(&expr) {
None => return None,
Some(expr) => expr,
};
debug!("Stripped Unicode word boundaries. New AST:\n{:?}", expr);
self.regex(&expr).ok()
});
Ok(Grep {
re: re,
required: literals.to_regex(),
required: required,
opts: self.opts,
})
}
/// Creates a new regex from the given expression with the current
/// configuration.
fn regex(&self, expr: &Expr) -> Result<Regex> {
let casei =
self.opts.case_insensitive
|| (self.opts.case_smart && !has_uppercase_literal(expr));
RegexBuilder::new(&expr.to_string())
.case_insensitive(casei)
.multi_line(true)
.unicode(true)
.size_limit(self.opts.size_limit)
.dfa_size_limit(self.opts.dfa_size_limit)
.compile()
.map_err(From::from)
}
/// Parses the underlying pattern and ensures the pattern can never match
/// the line terminator.
fn parse(&self) -> Result<syntax::Expr> {
@@ -152,7 +184,9 @@ impl GrepBuilder {
.unicode(true)
.case_insensitive(self.opts.case_insensitive)
.parse(&self.pattern));
Ok(try!(nonl::remove(expr, self.opts.line_terminator)))
let expr = try!(nonl::remove(expr, self.opts.line_terminator));
debug!("regex ast:\n{:#?}", expr);
Ok(expr)
}
}
@@ -194,7 +228,7 @@ impl Grep {
let (prevnl, nextnl) = self.find_line(buf, e, e);
match self.re.shortest_match(&buf[prevnl..nextnl]) {
None => {
start = nextnl + 1;
start = nextnl;
continue;
}
Some(_) => {
@@ -253,11 +287,28 @@ impl<'b, 's> Iterator for Iter<'b, 's> {
self.start = self.buf.len();
return None;
}
self.start = mat.end + 1;
self.start = mat.end;
Some(mat)
}
}
fn has_uppercase_literal(expr: &Expr) -> bool {
use syntax::Expr::*;
match *expr {
Literal { ref chars, casei } => {
casei || chars.iter().any(|c| c.is_uppercase())
}
LiteralBytes { ref bytes, casei } => {
casei || bytes.iter().any(|&b| b'A' <= b && b <= b'Z')
}
Group { ref e, .. } => has_uppercase_literal(e),
Repeat { ref e, .. } => has_uppercase_literal(e),
Concat(ref es) => es.iter().any(has_uppercase_literal),
Alternate(ref es) => es.iter().any(has_uppercase_literal),
_ => false,
}
}
#[cfg(test)]
mod tests {
#![allow(unused_imports)]

54
grep/src/word_boundary.rs Normal file
View File

@@ -0,0 +1,54 @@
use syntax::Expr;
/// Strips Unicode word boundaries from the given expression.
///
/// The key invariant this maintains is that the expression returned will match
/// *at least* every where the expression given will match. Namely, a match of
/// the returned expression can report false positives but it will never report
/// false negatives.
///
/// If no word boundaries could be stripped, then None is returned.
pub fn strip_unicode_word_boundaries(expr: &Expr) -> Option<Expr> {
// The real reason we do this is because Unicode word boundaries are the
// one thing that Rust's regex DFA engine can't handle. When it sees a
// Unicode word boundary among non-ASCII text, it falls back to one of the
// slower engines. We work around this limitation by attempting to use
// a regex to find candidate matches without a Unicode word boundary. We'll
// only then use the full (and slower) regex to confirm a candidate as a
// match or not during search.
use syntax::Expr::*;
match *expr {
Concat(ref es) if !es.is_empty() => {
let first = is_unicode_word_boundary(&es[0]);
let last = is_unicode_word_boundary(es.last().unwrap());
// Be careful not to strip word boundaries if there are no other
// expressions to match.
match (first, last) {
(true, false) if es.len() > 1 => {
Some(Concat(es[1..].to_vec()))
}
(false, true) if es.len() > 1 => {
Some(Concat(es[..es.len() - 1].to_vec()))
}
(true, true) if es.len() > 2 => {
Some(Concat(es[1..es.len() - 1].to_vec()))
}
_ => None,
}
}
_ => None,
}
}
/// Returns true if the given expression is a Unicode word boundary.
fn is_unicode_word_boundary(expr: &Expr) -> bool {
use syntax::Expr::*;
match *expr {
WordBoundary => true,
NotWordBoundary => true,
Group { ref e, .. } => is_unicode_word_boundary(e),
_ => false,
}
}

4
pkg/archlinux/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
*.xz
src
pkg
*.gz

36
pkg/archlinux/PKGBUILD Normal file
View File

@@ -0,0 +1,36 @@
# Contributor: Andrew Gallant <jamslam@gmail.com>
# Maintainer: Andrew Gallant
pkgname=ripgrep
pkgver=0.1.16
pkgrel=1
pkgdesc="A search tool that combines the usability of The Silver Searcher with the raw speed of grep."
arch=('i686' 'x86_64')
url="https://github.com/BurntSushi/ripgrep"
license=('UNLICENSE')
makedepends=('cargo')
source=("https://github.com/BurntSushi/$pkgname/archive/$pkgver.tar.gz")
sha256sums=('6f877018742c9a7557102ccebeedb40d7c779b470a5910a7bdab50ca2ce21532')
build() {
cd "$pkgname-$pkgver"
if command -v rustup > /dev/null 2>&1; then
RUSTFLAGS="-C target-cpu=native" rustup run nightly \
cargo build --release --features simd-accel
elif rustc --version | grep -q nightly; then
RUSTFLAGS="-C target-cpu=native" \
cargo build --release --features simd-accel
else
cargo build --release
fi
}
package() {
cd "$pkgname-$pkgver"
install -Dm755 "target/release/rg" "$pkgdir/usr/bin/rg"
install -Dm644 "doc/rg.1" "$pkgdir/usr/share/man/man1/rg.1"
install -Dm644 "README-NEW.md" "$pkgdir/usr/share/doc/ripgrep/README.md"
install -Dm644 "COPYING" "$pkgdir/usr/share/doc/ripgrep/COPYING"
install -Dm644 "LICENSE-MIT" "$pkgdir/usr/share/doc/ripgrep/LICENSE-MIT"
install -Dm644 "UNLICENSE" "$pkgdir/usr/share/doc/ripgrep/UNLICENSE"
}

14
pkg/brew/ripgrep-bin.rb Normal file
View File

@@ -0,0 +1,14 @@
class RipgrepBin < Formula
version '0.2.1'
desc "Search tool like grep and The Silver Searcher."
homepage "https://github.com/BurntSushi/ripgrep"
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
sha256 "f8b208239b988708da2e58f848a75bf70ad144e201b3ed99cd323cc5a699625f"
conflicts_with "ripgrep"
def install
bin.install "rg"
man1.install "rg.1"
end
end

View File

@@ -1 +0,0 @@
au BufWritePost *.rs silent!make ctags > /dev/null 2>&1

View File

@@ -9,14 +9,22 @@ use grep::{Grep, GrepBuilder};
use log;
use num_cpus;
use regex;
use term::Terminal;
#[cfg(not(windows))]
use term;
#[cfg(windows)]
use term::WinConsole;
use walkdir::WalkDir;
use atty;
use gitignore::{Gitignore, GitignoreBuilder};
use ignore::Ignore;
use out::Out;
use out::{Out, ColoredTerminal};
use printer::Printer;
use search::{InputBuffer, Searcher};
use sys;
use search_buffer::BufferSearcher;
use search_stream::{InputBuffer, Searcher};
#[cfg(windows)]
use terminal_win::WindowsBuffer;
use types::{FileTypeDef, Types, TypesBuilder};
use walk;
@@ -27,13 +35,14 @@ use Result;
/// If you've never heard of Docopt before, see: http://docopt.org
/// (TL;DR: The CLI parser is generated from the usage string below.)
const USAGE: &'static str = "
Usage: xrep [options] <pattern> [<path> ...]
xrep [options] --files [<path> ...]
xrep [options] --type-list
xrep --help
xrep --version
Usage: rg [options] -e PATTERN ... [<path> ...]
rg [options] <pattern> [<path> ...]
rg [options] --files [<path> ...]
rg [options] --type-list
rg [options] --help
rg [options] --version
xrep is like the silver searcher and grep, but faster than both.
rg recursively searches your current directory for a regex pattern.
Common options:
-a, --text Search binary files as if they were text.
@@ -41,6 +50,11 @@ Common options:
--color WHEN Whether to use coloring in match.
Valid values are never, always or auto.
[default: auto]
-e, --regexp PATTERN ... Use PATTERN to search. This option can be
provided multiple times, where all patterns
given are searched.
-F, --fixed-strings Treat the pattern as a literal string instead of
a regular expression.
-g, --glob GLOB ... Include or exclude files for searching that
match the given glob. This always overrides any
other ignore logic. Multiple glob flags may be
@@ -48,18 +62,23 @@ Common options:
Precede a glob with a '!' to exclude it.
-h, --help Show this usage message.
-i, --ignore-case Case insensitive search.
Overridden by --case-sensitive.
-n, --line-number Show line numbers (1-based). This is enabled
by default at a tty.
-N, --no-line-number Suppress line numbers.
-q, --quiet Do not print anything to stdout.
-r, --replace ARG Replace every match with the string given.
Capture group indices (e.g., $5) and names
(e.g., $foo) are supported.
-q, --quiet Do not print anything to stdout. If a match is
found in a file, stop searching that file.
-t, --type TYPE ... Only search files matching TYPE. Multiple type
flags may be provided. Use the --type-list flag
to list all available types.
-T, --type-not TYPE ... Do not search files matching TYPE. Multiple
not-type flags may be provided.
-u, --unrestricted ... Reduce the level of 'smart' searching. A
single -u doesn't respect .gitignore (etc.)
files. Two -u flags will search hidden files
and directories. Three -u flags will search
binary files. -uu is equivalent to grep -r,
and -uuu is equivalent to grep -a -r.
-v, --invert-match Invert matching.
-w, --word-regexp Only show matches surrounded by word boundaries.
This is equivalent to putting \\b before and
@@ -75,6 +94,11 @@ Less common options:
-C, --context NUM
Show NUM lines before and after each match.
--column
Show column numbers (1 based) in output. This only shows the column
numbers for the first match on each line. Note that this doesn't try
to account for Unicode. One byte is equal to one column.
--context-separator ARG
The string to use when separating non-continuous context lines. Escape
sequences may be used. [default: --]
@@ -85,10 +109,17 @@ Less common options:
--files
Print each file that would be searched (but don't search).
-l, --files-with-matches
Only show path of each file with matches.
-H, --with-filename
Prefix each match with the file name that contains it. This is the
default when more than one file is searched.
--no-filename
Never show the filename for a match. This is the default when
one file is searched.
--heading
Show the file name above clusters of matches from each file.
This is the default mode at a tty.
@@ -97,58 +128,105 @@ Less common options:
Don't show any file name heading.
--hidden
Search hidden directories and files.
Search hidden directories and files. (Hidden directories and files are
skipped by default.)
-L, --follow
Follow symlinks.
--line-terminator ARG
The byte to use for a line terminator. Escape sequences may be used.
[default: \\n]
--maxdepth NUM
Descend at most NUM directories below the command line arguments.
A value of zero only searches the starting-points themselves.
--mmap
Search using memory maps when possible. This is enabled by default
when ripgrep thinks it will be faster. (Note that mmap searching
doesn't currently support the various context related options.)
--no-mmap
Never use memory maps, even when they might be faster.
--no-ignore
Don't respect ignore files (.gitignore, .xrepignore, etc.)
Don't respect ignore files (.gitignore, .ignore, etc.)
This implies --no-ignore-parent.
--no-ignore-parent
Don't respect ignore files in parent directories.
--no-ignore-vcs
Don't respect version control ignore files (e.g., .gitignore).
Note that .ignore files will continue to be respected.
--null
Whenever a file name is printed, follow it with a NUL byte.
This includes printing filenames before matches, and when printing
a list of matching files such as with --count, --files-with-matches
and --files.
-p, --pretty
Alias for --color=always --heading -n.
-Q, --literal
Treat the pattern as a literal string instead of a regular expression.
-r, --replace ARG
Replace every match with the string given when printing search results.
Neither this flag nor any other flag will modify your files.
Capture group indices (e.g., $5) and names (e.g., $foo) are supported
in the replacement string.
-s, --case-sensitive
Search case sensitively. This overrides --ignore-case and --smart-case.
-S, --smart-case
Search case insensitively if the pattern is all lowercase.
Search case sensitively otherwise. This is overridden by
either --case-sensitive or --ignore-case.
-j, --threads ARG
The number of threads to use. Defaults to the number of logical CPUs
The number of threads to use. 0 means use the number of logical CPUs
(capped at 6). [default: 0]
--version
Show the version number of xrep and exit.
Show the version number of ripgrep and exit.
--vimgrep
Show results with every match on its own line, including line
numbers and column numbers. (With this option, a line with more
than one match of the regex will be printed more than once.)
File type management options:
--type-list
Show all supported file types and their associated globs.
--type-add ARG ...
Add a new glob for a particular file type.
Example: --type-add html:*.html,*.htm
Add a new glob for a particular file type. Only one glob can be
added at a time. Multiple --type-add flags can be provided.
Unless --type-clear is used, globs are added to any existing globs
inside of ripgrep. Note that this must be passed to every invocation of
rg. Type settings are NOT persisted.
Example: `rg --type-add 'foo:*.foo' -tfoo PATTERN`
--type-clear TYPE ...
Clear the file type globs for TYPE.
Clear the file type globs previously defined for TYPE. This only clears
the default type definitions that are found inside of ripgrep. Note
that this must be passed to every invocation of rg.
";
/// RawArgs are the args as they are parsed from Docopt. They aren't used
/// directly by the rest of xrep.
/// directly by the rest of ripgrep.
#[derive(Debug, RustcDecodable)]
pub struct RawArgs {
arg_pattern: String,
arg_path: Vec<String>,
flag_after_context: usize,
flag_before_context: usize,
flag_case_sensitive: bool,
flag_color: String,
flag_column: bool,
flag_context: usize,
flag_context_separator: String,
flag_count: bool,
flag_files_with_matches: bool,
flag_debug: bool,
flag_files: bool,
flag_follow: bool,
@@ -158,15 +236,22 @@ pub struct RawArgs {
flag_ignore_case: bool,
flag_invert_match: bool,
flag_line_number: bool,
flag_line_terminator: String,
flag_literal: bool,
flag_fixed_strings: bool,
flag_maxdepth: Option<usize>,
flag_mmap: bool,
flag_no_heading: bool,
flag_no_ignore: bool,
flag_no_ignore_parent: bool,
flag_no_ignore_vcs: bool,
flag_no_line_number: bool,
flag_no_mmap: bool,
flag_no_filename: bool,
flag_null: bool,
flag_pretty: bool,
flag_quiet: bool,
flag_regexp: Vec<String>,
flag_replace: Option<String>,
flag_smart_case: bool,
flag_text: bool,
flag_threads: usize,
flag_type: Vec<String>,
@@ -174,6 +259,8 @@ pub struct RawArgs {
flag_type_list: bool,
flag_type_add: Vec<String>,
flag_type_clear: Vec<String>,
flag_unrestricted: u32,
flag_vimgrep: bool,
flag_with_filename: bool,
flag_word_regexp: bool,
}
@@ -181,53 +268,49 @@ pub struct RawArgs {
/// Args are transformed/normalized from RawArgs.
#[derive(Debug)]
pub struct Args {
pattern: String,
paths: Vec<PathBuf>,
after_context: usize,
before_context: usize,
color: bool,
column: bool,
context_separator: Vec<u8>,
count: bool,
files_with_matches: bool,
eol: u8,
files: bool,
follow: bool,
glob_overrides: Option<Gitignore>,
grep: Grep,
heading: bool,
hidden: bool,
ignore_case: bool,
invert_match: bool,
line_number: bool,
line_per_match: bool,
maxdepth: Option<usize>,
mmap: bool,
no_ignore: bool,
no_ignore_parent: bool,
no_ignore_vcs: bool,
null: bool,
quiet: bool,
replace: Option<Vec<u8>>,
text: bool,
threads: usize,
type_defs: Vec<FileTypeDef>,
type_list: bool,
types: Types,
with_filename: bool,
}
impl RawArgs {
/// Convert arguments parsed into a configuration used by xrep.
/// Convert arguments parsed into a configuration used by ripgrep.
fn to_args(&self) -> Result<Args> {
let pattern = {
let pattern =
if self.flag_literal {
regex::quote(&self.arg_pattern)
} else {
self.arg_pattern.clone()
};
if self.flag_word_regexp {
format!(r"\b{}\b", pattern)
} else {
pattern
}
};
let paths =
if self.arg_path.is_empty() {
if sys::stdin_is_atty() {
if atty::on_stdin()
|| self.flag_files
|| self.flag_type_list
|| !atty::stdin_is_readable() {
vec![Path::new("./").to_path_buf()]
} else {
vec![Path::new("-").to_path_buf()]
@@ -243,15 +326,25 @@ impl RawArgs {
} else {
(self.flag_after_context, self.flag_before_context)
};
let eol = {
let eol = unescape(&self.flag_line_terminator);
if eol.is_empty() {
errored!("Empty line terminator is not allowed.");
} else if eol.len() > 1 {
errored!("Line terminators are limited to exactly 1 byte.");
}
eol[0]
};
let mmap =
if before_context > 0 || after_context > 0 || self.flag_no_mmap {
false
} else if self.flag_mmap {
true
} else if cfg!(windows) {
// On Windows, memory maps appear faster than read calls. Neat.
true
} else if cfg!(target_os = "macos") {
// On Mac, memory maps appear to suck. Neat.
false
} else {
// If we're only searching a few paths and all of them are
// files, then memory maps are probably faster.
paths.len() <= 10 && paths.iter().all(|p| p.is_file())
};
if mmap {
debug!("will try to use memory maps");
}
let glob_overrides =
if self.flag_glob.is_empty() {
None
@@ -265,54 +358,70 @@ impl RawArgs {
};
let threads =
if self.flag_threads == 0 {
cmp::min(6, num_cpus::get())
cmp::min(8, num_cpus::get())
} else {
self.flag_threads
};
let color =
if self.flag_color == "auto" {
sys::stdout_is_atty() || self.flag_pretty
if self.flag_color == "always" {
true
} else if self.flag_vimgrep {
false
} else if self.flag_color == "auto" {
atty::on_stdout() || self.flag_pretty
} else {
self.flag_color == "always"
false
};
let mut with_filename = self.flag_with_filename;
if !with_filename {
with_filename = paths.len() > 1 || paths[0].is_dir();
}
let mut btypes = TypesBuilder::new();
btypes.add_defaults();
try!(self.add_types(&mut btypes));
let types = try!(btypes.build());
with_filename = with_filename && !self.flag_no_filename;
let no_ignore = self.flag_no_ignore || self.flag_unrestricted >= 1;
let hidden = self.flag_hidden || self.flag_unrestricted >= 2;
let text = self.flag_text || self.flag_unrestricted >= 3;
let mut args = Args {
pattern: pattern,
paths: paths,
after_context: after_context,
before_context: before_context,
color: color,
column: self.flag_column,
context_separator: unescape(&self.flag_context_separator),
count: self.flag_count,
eol: eol,
files_with_matches: self.flag_files_with_matches,
eol: self.eol(),
files: self.flag_files,
follow: self.flag_follow,
glob_overrides: glob_overrides,
grep: try!(self.grep()),
heading: !self.flag_no_heading && self.flag_heading,
hidden: self.flag_hidden,
hidden: hidden,
ignore_case: self.flag_ignore_case,
invert_match: self.flag_invert_match,
line_number: !self.flag_no_line_number && self.flag_line_number,
no_ignore: self.flag_no_ignore,
no_ignore_parent: self.flag_no_ignore_parent,
line_per_match: self.flag_vimgrep,
maxdepth: self.flag_maxdepth,
mmap: mmap,
no_ignore: no_ignore,
no_ignore_parent:
// --no-ignore implies --no-ignore-parent
self.flag_no_ignore_parent || no_ignore,
no_ignore_vcs:
// --no-ignore implies --no-ignore-vcs
self.flag_no_ignore_vcs || no_ignore,
null: self.flag_null,
quiet: self.flag_quiet,
replace: self.flag_replace.clone().map(|s| s.into_bytes()),
text: self.flag_text,
text: text,
threads: threads,
type_defs: btypes.definitions(),
type_list: self.flag_type_list,
types: types,
types: try!(self.types()),
with_filename: with_filename,
};
// If stdout is a tty, then apply some special default options.
if sys::stdout_is_atty() || self.flag_pretty {
if atty::on_stdout() || self.flag_pretty {
if !self.flag_no_line_number && !args.count {
args.line_number = true;
}
@@ -320,23 +429,78 @@ impl RawArgs {
args.heading = true;
}
}
if self.flag_vimgrep {
args.column = true;
args.line_number = true;
}
Ok(args)
}
fn add_types(&self, types: &mut TypesBuilder) -> Result<()> {
fn types(&self) -> Result<Types> {
let mut btypes = TypesBuilder::new();
btypes.add_defaults();
for ty in &self.flag_type_clear {
types.clear(ty);
btypes.clear(ty);
}
for def in &self.flag_type_add {
try!(types.add_def(def));
try!(btypes.add_def(def));
}
for ty in &self.flag_type {
types.select(ty);
btypes.select(ty);
}
for ty in &self.flag_type_not {
types.select_not(ty);
btypes.negate(ty);
}
Ok(())
btypes.build().map_err(From::from)
}
fn pattern(&self) -> String {
if !self.flag_regexp.is_empty() {
if self.flag_fixed_strings {
self.flag_regexp.iter().cloned().map(|lit| {
self.word_pattern(regex::quote(&lit))
}).collect::<Vec<String>>().join("|")
} else {
self.flag_regexp.iter().cloned().map(|pat| {
self.word_pattern(pat)
}).collect::<Vec<String>>().join("|")
}
} else {
if self.flag_fixed_strings {
self.word_pattern(regex::quote(&self.arg_pattern))
} else {
self.word_pattern(self.arg_pattern.clone())
}
}
}
fn word_pattern(&self, s: String) -> String {
if self.flag_word_regexp {
format!(r"\b{}\b", s)
} else {
s
}
}
fn eol(&self) -> u8 {
// We might want to make this configurable.
b'\n'
}
fn grep(&self) -> Result<Grep> {
let smart =
self.flag_smart_case
&& !self.flag_ignore_case
&& !self.flag_case_sensitive;
let casei =
self.flag_ignore_case
&& !self.flag_case_sensitive;
GrepBuilder::new(&self.pattern())
.case_smart(smart)
.case_insensitive(casei)
.line_terminator(self.eol())
.build()
.map_err(From::from)
}
}
@@ -345,13 +509,26 @@ impl Args {
///
/// If a CLI usage error occurred, then exit the process and print a usage
/// or error message. Similarly, if the user requested the version of
/// xrep, then print the version and exit.
/// ripgrep, then print the version and exit.
///
/// Also, initialize a global logger.
pub fn parse() -> Result<Args> {
let raw: RawArgs =
// Get all of the arguments, being careful to require valid UTF-8.
let mut argv = vec![];
for arg in env::args_os() {
match arg.into_string() {
Ok(s) => argv.push(s),
Err(s) => {
errored!("Argument '{}' is not valid UTF-8. \
Use hex escape sequences to match arbitrary \
bytes in a pattern (e.g., \\xFF).",
s.to_string_lossy());
}
}
}
let mut raw: RawArgs =
Docopt::new(USAGE)
.and_then(|d| d.version(Some(version())).decode())
.and_then(|d| d.argv(argv).version(Some(version())).decode())
.unwrap_or_else(|e| e.exit());
let mut logb = env_logger::LogBuilder::new();
@@ -364,10 +541,17 @@ impl Args {
errored!("failed to initialize logger: {}", err);
}
// *sigh*... If --files is given, then the first path ends up in
// pattern.
if raw.flag_files {
if !raw.arg_pattern.is_empty() {
raw.arg_path.insert(0, raw.arg_pattern.clone());
}
}
raw.to_args().map_err(From::from)
}
/// Returns true if xrep should print the files it will search and exit
/// Returns true if ripgrep should print the files it will search and exit
/// (but not do any actual searching).
pub fn files(&self) -> bool {
self.files
@@ -378,12 +562,8 @@ impl Args {
/// basic searching of regular expressions in a single buffer.
///
/// The pattern and other flags are taken from the command line.
pub fn grep(&self) -> Result<Grep> {
GrepBuilder::new(&self.pattern)
.case_insensitive(self.ignore_case)
.line_terminator(self.eol)
.build()
.map_err(From::from)
pub fn grep(&self) -> Grep {
self.grep.clone()
}
/// Creates a new input buffer that is used in searching.
@@ -393,14 +573,26 @@ impl Args {
inp
}
/// Whether we should prefer memory maps for searching or not.
pub fn mmap(&self) -> bool {
self.mmap
}
/// Whether ripgrep should be quiet or not.
pub fn quiet(&self) -> bool {
self.quiet
}
/// Create a new printer of individual search results that writes to the
/// writer given.
pub fn printer<W: Send + io::Write>(&self, wtr: W) -> Printer<W> {
let mut p = Printer::new(wtr, self.color)
pub fn printer<W: Terminal + Send>(&self, wtr: W) -> Printer<W> {
let mut p = Printer::new(wtr)
.column(self.column)
.context_separator(self.context_separator.clone())
.eol(self.eol)
.heading(self.heading)
.quiet(self.quiet)
.line_per_match(self.line_per_match)
.null(self.null)
.with_filename(self.with_filename);
if let Some(ref rep) = self.replace {
p = p.replace(rep.clone());
@@ -410,16 +602,51 @@ impl Args {
/// Create a new printer of search results for an entire file that writes
/// to the writer given.
pub fn out<W: io::Write>(&self, wtr: W) -> Out<W> {
let mut out = Out::new(wtr);
if self.heading && !self.count {
out = out.file_separator(b"".to_vec());
} else if self.before_context > 0 || self.after_context > 0 {
out = out.file_separator(self.context_separator.clone());
pub fn out(&self) -> Out {
let mut out = Out::new(self.color);
if let Some(filesep) = self.file_separator() {
out = out.file_separator(filesep);
}
out
}
/// Retrieve the configured file separator.
pub fn file_separator(&self) -> Option<Vec<u8>> {
if self.heading && !self.count && !self.files_with_matches {
Some(b"".to_vec())
} else if self.before_context > 0 || self.after_context > 0 {
Some(self.context_separator.clone())
} else {
None
}
}
/// Create a new buffer for use with searching.
#[cfg(not(windows))]
pub fn outbuf(&self) -> ColoredTerminal<term::TerminfoTerminal<Vec<u8>>> {
ColoredTerminal::new(vec![], self.color)
}
/// Create a new buffer for use with searching.
#[cfg(windows)]
pub fn outbuf(&self) -> ColoredTerminal<WindowsBuffer> {
ColoredTerminal::new_buffer(self.color)
}
/// Create a new buffer for use with searching.
#[cfg(not(windows))]
pub fn stdout(
&self,
) -> ColoredTerminal<term::TerminfoTerminal<io::BufWriter<io::Stdout>>> {
ColoredTerminal::new(io::BufWriter::new(io::stdout()), self.color)
}
/// Create a new buffer for use with searching.
#[cfg(windows)]
pub fn stdout(&self) -> ColoredTerminal<WinConsole<io::Stdout>> {
ColoredTerminal::new_stdout(self.color)
}
/// Return the paths that should be searched.
pub fn paths(&self) -> &[PathBuf] {
&self.paths
@@ -428,7 +655,7 @@ impl Args {
/// Create a new line based searcher whose configuration is taken from the
/// command line. This searcher supports a dizzying array of features:
/// inverted matching, line counting, context control and more.
pub fn searcher<'a, R: io::Read, W: Send + io::Write>(
pub fn searcher<'a, R: io::Read, W: Send + Terminal>(
&self,
inp: &'a mut InputBuffer,
printer: &'a mut Printer<W>,
@@ -440,9 +667,31 @@ impl Args {
.after_context(self.after_context)
.before_context(self.before_context)
.count(self.count)
.files_with_matches(self.files_with_matches)
.eol(self.eol)
.line_number(self.line_number)
.invert_match(self.invert_match)
.quiet(self.quiet)
.text(self.text)
}
/// Create a new line based searcher whose configuration is taken from the
/// command line. This search operates on an entire file all once (which
/// may have been memory mapped).
pub fn searcher_buffer<'a, W: Send + Terminal>(
&self,
printer: &'a mut Printer<W>,
grep: &'a Grep,
path: &'a Path,
buf: &'a [u8],
) -> BufferSearcher<'a, W> {
BufferSearcher::new(printer, grep, path, buf)
.count(self.count)
.files_with_matches(self.files_with_matches)
.eol(self.eol)
.line_number(self.line_number)
.invert_match(self.invert_match)
.quiet(self.quiet)
.text(self.text)
}
@@ -453,27 +702,38 @@ impl Args {
/// Returns a list of type definitions currently loaded.
pub fn type_defs(&self) -> &[FileTypeDef] {
&self.type_defs
self.types.definitions()
}
/// Returns true if xrep should print the type definitions currently loaded
/// and then exit.
/// Returns true if ripgrep should print the type definitions currently
/// loaded and then exit.
pub fn type_list(&self) -> bool {
self.type_list
}
/// Create a new recursive directory iterator at the path given.
pub fn walker(&self, path: &Path) -> Result<walk::Iter> {
let wd = WalkDir::new(path).follow_links(self.follow);
let mut ig = Ignore::new();
ig.ignore_hidden(!self.hidden);
ig.no_ignore(self.no_ignore);
ig.add_types(self.types.clone());
if !self.no_ignore_parent {
try!(ig.push_parents(path));
// Always follow symlinks for explicitly specified files.
let mut wd = WalkDir::new(path).follow_links(
self.follow || path.is_file());
if let Some(maxdepth) = self.maxdepth {
wd = wd.max_depth(maxdepth);
}
if let Some(ref overrides) = self.glob_overrides {
ig.add_override(overrides.clone());
let mut ig = Ignore::new();
// Only register ignore rules if this is a directory. If it's a file,
// then it was explicitly given by the end user, so we always search
// it.
if path.is_dir() {
ig.ignore_hidden(!self.hidden);
ig.no_ignore(self.no_ignore);
ig.no_ignore_vcs(self.no_ignore_vcs);
ig.add_types(self.types.clone());
if !self.no_ignore_parent {
try!(ig.push_parents(path));
}
if let Some(ref overrides) = self.glob_overrides {
ig.add_override(overrides.clone());
}
}
Ok(walk::Iter::new(ig, wd))
}

69
src/atty.rs Normal file
View File

@@ -0,0 +1,69 @@
/*!
This atty module contains functions for detecting whether ripgrep is being fed
from (or to) a terminal. Windows and Unix do this differently, so implement
both here.
*/
#[cfg(unix)]
pub fn stdin_is_readable() -> bool {
use std::fs::File;
use std::os::unix::fs::FileTypeExt;
use std::os::unix::io::{FromRawFd, IntoRawFd};
use libc;
let file = unsafe { File::from_raw_fd(libc::STDIN_FILENO) };
let md = file.metadata();
let _ = file.into_raw_fd();
let ft = match md {
Err(_) => return false,
Ok(md) => md.file_type(),
};
ft.is_file() || ft.is_fifo()
}
#[cfg(windows)]
pub fn stdin_is_readable() -> bool {
// ???
true
}
/// Returns true if there is a tty on stdin.
#[cfg(unix)]
pub fn on_stdin() -> bool {
use libc;
0 < unsafe { libc::isatty(libc::STDIN_FILENO) }
}
/// Returns true if there is a tty on stdout.
#[cfg(unix)]
pub fn on_stdout() -> bool {
use libc;
0 < unsafe { libc::isatty(libc::STDOUT_FILENO) }
}
/// Returns true if there is a tty on stdin.
#[cfg(windows)]
pub fn on_stdin() -> bool {
// BUG: https://github.com/BurntSushi/ripgrep/issues/19
// It's not clear to me how to determine whether there is a tty on stdin.
// Checking GetConsoleMode(GetStdHandle(stdin)) != 0 appears to report
// that stdin is a pipe, even if it's not in a cygwin terminal, for
// example.
//
// To fix this, we just assume there is always a tty on stdin. If Windows
// users need to search stdin, they'll have to pass -. Ug.
true
}
/// Returns true if there is a tty on stdout.
#[cfg(windows)]
pub fn on_stdout() -> bool {
use kernel32;
use winapi;
unsafe {
let fd = winapi::winbase::STD_OUTPUT_HANDLE;
let mut out = 0;
kernel32::GetConsoleMode(kernel32::GetStdHandle(fd), &mut out) != 0
}
}

View File

@@ -9,7 +9,7 @@ The motivation for this submodule is performance and portability:
2. We could shell out to a `git` sub-command like ls-files or status, but it
seems better to not rely on the existence of external programs for a search
tool. Besides, we need to implement this logic anyway to support things like
an .xrepignore file.
an .ignore file.
The key implementation detail here is that a single gitignore file is compiled
into a single RegexSet, which can be used to report which globs match a
@@ -21,21 +21,24 @@ additional rules such as whitelists (prefix of `!`) or directory-only globs
// TODO(burntsushi): Implement something similar, but for Mercurial. We can't
// use this exact implementation because hgignore files are different.
use std::env;
use std::cell::RefCell;
use std::error::Error as StdError;
use std::fmt;
use std::fs::File;
use std::io::{self, BufRead};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use globset::{self, Candidate, GlobBuilder, GlobSet, GlobSetBuilder};
use regex;
use thread_local::ThreadLocal;
use glob;
use pathutil::{is_file_name, strip_prefix};
/// Represents an error that can occur when parsing a gitignore file.
#[derive(Debug)]
pub enum Error {
Glob(glob::Error),
Glob(globset::Error),
Regex(regex::Error),
Io(io::Error),
}
@@ -60,8 +63,8 @@ impl fmt::Display for Error {
}
}
impl From<glob::Error> for Error {
fn from(err: glob::Error) -> Error {
impl From<globset::Error> for Error {
fn from(err: globset::Error) -> Error {
Error::Glob(err)
}
}
@@ -81,29 +84,19 @@ impl From<io::Error> for Error {
/// Gitignore is a matcher for the glob patterns in a single gitignore file.
#[derive(Clone, Debug)]
pub struct Gitignore {
set: glob::Set,
set: GlobSet,
root: PathBuf,
patterns: Vec<Pattern>,
num_ignores: u64,
num_whitelist: u64,
matches: Arc<ThreadLocal<RefCell<Vec<usize>>>>,
}
impl Gitignore {
/// Create a new gitignore glob matcher from the gitignore file at the
/// given path. The root of the gitignore file is the basename of path.
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Gitignore, Error> {
let root = match path.as_ref().parent() {
Some(parent) => parent.to_path_buf(),
None => env::current_dir().unwrap_or(Path::new("/").to_path_buf()),
};
let mut builder = GitignoreBuilder::new(root);
try!(builder.add_path(path));
builder.build()
}
/// Create a new gitignore glob matcher from the given root directory and
/// string containing the contents of a gitignore file.
pub fn from_str<P: AsRef<Path>>(
#[allow(dead_code)]
fn from_str<P: AsRef<Path>>(
root: P,
gitignore: &str,
) -> Result<Gitignore, Error> {
@@ -122,27 +115,32 @@ impl Gitignore {
/// same directory as this gitignore file.
pub fn matched<P: AsRef<Path>>(&self, path: P, is_dir: bool) -> Match {
let mut path = path.as_ref();
if let Ok(p) = path.strip_prefix(&self.root) {
if let Some(p) = strip_prefix("./", path) {
path = p;
}
self.matched_utf8(&*path.to_string_lossy(), is_dir)
// Strip any common prefix between the candidate path and the root
// of the gitignore, to make sure we get relative matching right.
// BUT, a file name might not have any directory components to it,
// in which case, we don't want to accidentally strip any part of the
// file name.
if !is_file_name(path) {
if let Some(p) = strip_prefix(&self.root, path) {
path = p;
}
}
if let Some(p) = strip_prefix("/", path) {
path = p;
}
self.matched_stripped(path, is_dir)
}
/// Like matched, but takes a path that has already been stripped and
/// converted to UTF-8.
pub fn matched_utf8(&self, path: &str, is_dir: bool) -> Match {
// A single regex with a bunch of alternations of glob patterns is
// unfortunately typically faster than a regex, so we use it as a
// first pass filter. We still need to run the RegexSet to get the most
// recently defined glob that matched.
if !self.set.is_match(path) {
return Match::None;
}
// The regex set can't actually pick the right glob that matched all
// on its own. In particular, some globs require that only directories
// can match. Thus, only accept a match from the regex set if the given
// path satisfies the corresponding glob's directory criteria.
for i in self.set.matches(path).iter().rev() {
/// Like matched, but takes a path that has already been stripped.
pub fn matched_stripped(&self, path: &Path, is_dir: bool) -> Match {
let _matches = self.matches.get_default();
let mut matches = _matches.borrow_mut();
let candidate = Candidate::new(path);
self.set.matches_candidate_into(&candidate, &mut *matches);
for &i in matches.iter().rev() {
let pat = &self.patterns[i];
if !pat.only_dir || is_dir {
return if pat.whitelist {
@@ -159,11 +157,6 @@ impl Gitignore {
pub fn num_ignores(&self) -> u64 {
self.num_ignores
}
/// Returns the total number of whitelisted patterns.
pub fn num_whitelist(&self) -> u64 {
self.num_whitelist
}
}
/// The result of a glob match.
@@ -182,6 +175,7 @@ pub enum Match<'a> {
impl<'a> Match<'a> {
/// Returns true if the match result implies the path should be ignored.
#[allow(dead_code)]
pub fn is_ignored(&self) -> bool {
match *self {
Match::Ignored(_) => true,
@@ -211,7 +205,7 @@ impl<'a> Match<'a> {
/// GitignoreBuilder constructs a matcher for a single set of globs from a
/// .gitignore file.
pub struct GitignoreBuilder {
builder: glob::SetBuilder,
builder: GlobSetBuilder,
root: PathBuf,
patterns: Vec<Pattern>,
}
@@ -239,9 +233,10 @@ impl GitignoreBuilder {
/// The path given should be the path at which the globs for this gitignore
/// file should be matched.
pub fn new<P: AsRef<Path>>(root: P) -> GitignoreBuilder {
let root = strip_prefix("./", root.as_ref()).unwrap_or(root.as_ref());
GitignoreBuilder {
builder: glob::SetBuilder::new(),
root: root.as_ref().to_path_buf(),
builder: GlobSetBuilder::new(),
root: root.to_path_buf(),
patterns: vec![],
}
}
@@ -258,14 +253,26 @@ impl GitignoreBuilder {
patterns: self.patterns,
num_ignores: nignores as u64,
num_whitelist: nwhitelist as u64,
matches: Arc::new(ThreadLocal::default()),
})
}
/// Add each pattern line from the file path given.
pub fn add_path<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error> {
let rdr = io::BufReader::new(try!(File::open(&path)));
for line in rdr.lines() {
try!(self.add(&path, &try!(line)));
debug!("gitignore: {}", path.as_ref().display());
for (i, line) in rdr.lines().enumerate() {
let line = match line {
Ok(line) => line,
Err(err) => {
debug!("error reading line {} in {}: {}",
i, path.as_ref().display(), err);
continue;
}
};
if let Err(err) = self.add(&path, &line) {
debug!("error adding gitignore pattern: '{}': {}", line, err);
}
}
Ok(())
}
@@ -286,6 +293,12 @@ impl GitignoreBuilder {
from: P,
mut line: &str,
) -> Result<(), Error> {
if line.starts_with("#") {
return Ok(());
}
if !line.ends_with("\\ ") {
line = line.trim_right();
}
if line.is_empty() {
return Ok(());
}
@@ -296,34 +309,24 @@ impl GitignoreBuilder {
whitelist: false,
only_dir: false,
};
let mut opts = glob::MatchOptions::default();
let mut literal_separator = false;
let has_slash = line.chars().any(|c| c == '/');
// If the line starts with an escaped '!', then remove the escape.
// Otherwise, if it starts with an unescaped '!', then this is a
// whitelist pattern.
match line.chars().nth(0) {
Some('#') => return Ok(()),
Some('\\') => {
match line.chars().nth(1) {
Some('!') | Some('#') => {
line = &line[1..];
}
_ => {}
}
}
Some('!') => {
let is_absolute = line.chars().nth(0).unwrap() == '/';
if line.starts_with("\\!") || line.starts_with("\\#") {
line = &line[1..];
} else {
if line.starts_with("!") {
pat.whitelist = true;
line = &line[1..];
}
Some('/') => {
if line.starts_with("/") {
// `man gitignore` says that if a glob starts with a slash,
// then the glob can only match the beginning of a path
// (relative to the location of gitignore). We achieve this by
// simply banning wildcards from matching /.
opts.require_literal_separator = true;
literal_separator = true;
line = &line[1..];
}
_ => {}
}
// If it ends with a slash, then this should only match directories,
// but the slash should otherwise not be used while globbing.
@@ -334,16 +337,31 @@ impl GitignoreBuilder {
}
}
// If there is a literal slash, then we note that so that globbing
// doesn't let wildcards match slashes. Otherwise, we need to let
// the pattern match anywhere, so we add a `**/` prefix to achieve
// that behavior.
// doesn't let wildcards match slashes.
pat.pat = line.to_string();
if has_slash {
opts.require_literal_separator = true;
} else {
pat.pat = format!("**/{}", pat.pat);
literal_separator = true;
}
try!(self.builder.add_with(&pat.pat, &opts));
// If there was a leading slash, then this is a pattern that must
// match the entire path name. Otherwise, we should let it match
// anywhere, so use a **/ prefix.
if !is_absolute {
// ... but only if we don't already have a **/ prefix.
if !pat.pat.starts_with("**/") {
pat.pat = format!("**/{}", pat.pat);
}
}
// If the pattern ends with `/**`, then we should only match everything
// inside a directory, but not the directory itself. Standard globs
// will match the directory. So we add `/*` to force the issue.
if pat.pat.ends_with("/**") {
pat.pat = format!("{}/*", pat.pat);
}
let parsed = try!(
GlobBuilder::new(&pat.pat)
.literal_separator(literal_separator)
.build());
self.builder.add(parsed);
self.patterns.push(pat);
Ok(())
}
@@ -379,7 +397,7 @@ mod tests {
};
}
const ROOT: &'static str = "/home/foobar/rust/xrep";
const ROOT: &'static str = "/home/foobar/rust/rg";
ignored!(ig1, ROOT, "months", "months");
ignored!(ig2, ROOT, "*.lock", "Cargo.lock");
@@ -406,10 +424,15 @@ mod tests {
ignored!(ig23, ROOT, "foo", "./foo");
ignored!(ig24, ROOT, "target", "grep/target");
ignored!(ig25, ROOT, "Cargo.lock", "./tabwriter-bin/Cargo.lock");
ignored!(ig26, ROOT, "/foo/bar/baz", "./foo/bar/baz");
ignored!(ig27, ROOT, "foo/", "xyz/foo", true);
ignored!(ig28, ROOT, "src/*.rs", "src/grep/src/main.rs");
ignored!(ig29, "./src", "/llvm/", "./src/llvm", true);
ignored!(ig30, ROOT, "node_modules/ ", "node_modules", true);
not_ignored!(ignot1, ROOT, "amonths", "months");
not_ignored!(ignot2, ROOT, "monthsa", "months");
not_ignored!(ignot3, ROOT, "src/*.rs", "src/grep/src/main.rs");
not_ignored!(ignot3, ROOT, "/src/*.rs", "src/grep/src/main.rs");
not_ignored!(ignot4, ROOT, "/*.c", "mozilla-sha1/sha1.c");
not_ignored!(ignot5, ROOT, "/src/*.rs", "src/grep/src/main.rs");
not_ignored!(ignot6, ROOT, "*.rs\n!src/main.rs", "src/main.rs");
@@ -419,4 +442,14 @@ mod tests {
not_ignored!(ignot10, ROOT, "**/foo/bar", "foo/src/bar");
not_ignored!(ignot11, ROOT, "#foo", "#foo");
not_ignored!(ignot12, ROOT, "\n\n\n", "foo");
not_ignored!(ignot13, ROOT, "foo/**", "foo", true);
not_ignored!(
ignot14, "./third_party/protobuf", "m4/ltoptions.m4",
"./third_party/protobuf/csharp/src/packages/repositories.config");
// See: https://github.com/BurntSushi/ripgrep/issues/106
#[test]
fn regression_106() {
Gitignore::from_str("/", " ").unwrap();
}
}

View File

@@ -1,690 +0,0 @@
/*!
The glob module provides standard shell globbing, but is specifically
implemented by converting glob syntax to regular expressions. The reasoning is
two fold:
1. The regex library is *really* fast. Regaining performance in a distinct
implementation of globbing is non-trivial.
2. Most crucially, a `RegexSet` can be used to match many globs simultaneously.
This module is written with some amount of intention of eventually splitting it
out into its own separate crate, but I didn't quite have the energy for all
that rigamorole when I wrote this. In particular, it could be fast/good enough
to make its way into `glob` proper.
*/
// TODO(burntsushi): I'm pretty dismayed by the performance of regex sets
// here. For example, we do a first pass single-regex-of-all-globs filter
// before actually running the regex set. This turns out to be faster,
// especially in fresh checkouts of repos that don't have a lot of ignored
// files. It's not clear how hard it is to make the regex set faster.
//
// An alternative avenue is to stop doing "regex all the things." (Which, to
// be fair, is pretty fast---I just expected it to be faster.) We could do
// something clever using assumptions along the lines of "oh, most ignore
// patterns are either literals or are for ignoring file extensions." (Look
// at the .gitignore for the chromium repo---just about every pattern satisfies
// that assumption.)
use std::error::Error as StdError;
use std::fmt;
use std::iter;
use std::path;
use std::str;
use regex;
use regex::bytes::{Regex, RegexSet, SetMatches};
/// Represents an error that can occur when parsing a glob pattern.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Error {
InvalidRecursive,
UnclosedClass,
InvalidRange(char, char),
}
impl StdError for Error {
fn description(&self) -> &str {
match *self {
Error::InvalidRecursive => {
"invalid use of **; must be one path component"
}
Error::UnclosedClass => {
"unclosed character class; missing ']'"
}
Error::InvalidRange(_, _) => {
"invalid character range"
}
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::InvalidRecursive | Error::UnclosedClass => {
write!(f, "{}", self.description())
}
Error::InvalidRange(s, e) => {
write!(f, "invalid range; '{}' > '{}'", s, e)
}
}
}
}
/// Set represents a group of globs that can be matched together in a single
/// pass.
#[derive(Clone, Debug)]
pub struct Set {
re: Regex,
set: RegexSet,
}
impl Set {
/// Returns true if and only if the given path matches at least one glob
/// in this set.
pub fn is_match<T: AsRef<[u8]>>(&self, path: T) -> bool {
self.re.is_match(path.as_ref())
}
/// Returns every glob pattern (by sequence number) that matches the given
/// path.
pub fn matches<T: AsRef<[u8]>>(&self, path: T) -> SetMatches {
// TODO(burntsushi): If we split this out into a separate crate, don't
// expose the regex::SetMatches type in the public API.
self.set.matches(path.as_ref())
}
/// Returns the number of glob patterns in this set.
pub fn len(&self) -> usize {
self.set.len()
}
}
/// SetBuilder builds a group of patterns that can be used to simultaneously
/// match a file path.
pub struct SetBuilder {
pats: Vec<(Pattern, MatchOptions)>,
}
impl SetBuilder {
/// Create a new SetBuilder. A SetBuilder can be used to add new patterns.
/// Once all patterns have been added, `build` should be called to produce
/// a `Set`, which can then be used for matching.
pub fn new() -> SetBuilder {
SetBuilder { pats: vec![] }
}
/// Builds a new matcher from all of the glob patterns added so far.
///
/// Once a matcher is built, no new patterns can be added to it.
pub fn build(&self) -> Result<Set, regex::Error> {
let it = self.pats.iter().map(|&(ref p, ref o)| p.to_regex_with(o));
let set = try!(RegexSet::new(it));
let mut joined = String::new();
for &(ref p, ref o) in &self.pats {
let part = format!("(?:{})", p.to_regex_with(o));
if !joined.is_empty() {
joined.push('|');
}
joined.push_str(&part);
}
let re = try!(Regex::new(&joined));
Ok(Set { re: re, set: set })
}
/// Add a new pattern to this set.
///
/// If the pattern could not be parsed as a glob, then an error is
/// returned.
pub fn add(&mut self, pat: &str) -> Result<(), Error> {
self.add_with(pat, &MatchOptions::default())
}
/// Like add, but sets the match options for this particular pattern.
pub fn add_with(
&mut self,
pat: &str,
opts: &MatchOptions,
) -> Result<(), Error> {
let pat = try!(Pattern::new(pat));
self.pats.push((pat, opts.clone()));
Ok(())
}
}
/// Pattern represents a successfully parsed shell glob pattern.
///
/// It cannot be used directly to match file paths, but it can be converted
/// to a regular expression string.
#[derive(Clone, Debug, Default)]
pub struct Pattern {
tokens: Vec<Token>,
}
/// Options to control the matching semantics of a glob. The default value
/// has all options disabled.
#[derive(Clone, Debug, Default)]
pub struct MatchOptions {
/// When true, matching is done case insensitively.
pub case_insensitive: bool,
/// When true, neither `*` nor `?` match the current system's path
/// separator.
pub require_literal_separator: bool,
}
#[derive(Clone, Debug, Eq, PartialEq)]
enum Token {
Literal(char),
Any,
ZeroOrMore,
RecursivePrefix,
RecursiveSuffix,
RecursiveZeroOrMore,
Class {
negated: bool,
ranges: Vec<(char, char)>,
},
}
impl Pattern {
/// Parse a shell glob pattern.
///
/// If the pattern is not a valid glob, then an error is returned.
pub fn new(pat: &str) -> Result<Pattern, Error> {
let mut p = Parser {
p: Pattern::default(),
chars: pat.chars().peekable(),
prev: None,
cur: None,
};
try!(p.parse());
Ok(p.p)
}
/// Convert this pattern to a string that is guaranteed to be a valid
/// regular expression and will represent the matching semantics of this
/// glob pattern. This uses a default set of options.
pub fn to_regex(&self) -> String {
self.to_regex_with(&MatchOptions::default())
}
/// Convert this pattern to a string that is guaranteed to be a valid
/// regular expression and will represent the matching semantics of this
/// glob pattern and the options given.
pub fn to_regex_with(&self, options: &MatchOptions) -> String {
let sep = regex::quote(&path::MAIN_SEPARATOR.to_string());
let mut re = String::new();
re.push_str("(?-u)");
if options.case_insensitive {
re.push_str("(?i)");
}
re.push('^');
// Special case. If the entire glob is just `**`, then it should match
// everything.
if self.tokens.len() == 1 && self.tokens[0] == Token::RecursivePrefix {
re.push_str(".*");
re.push('$');
return re;
}
for tok in &self.tokens {
match *tok {
Token::Literal(c) => {
re.push_str(&regex::quote(&c.to_string()));
}
Token::Any => {
if options.require_literal_separator {
re.push_str(&format!("[^{}]", sep));
} else {
re.push_str(".");
}
}
Token::ZeroOrMore => {
if options.require_literal_separator {
re.push_str(&format!("[^{}]*", sep));
} else {
re.push_str(".*");
}
}
Token::RecursivePrefix => {
re.push_str(&format!("(?:{sep}?|.*{sep})", sep=sep));
}
Token::RecursiveSuffix => {
re.push_str(&format!("(?:{sep}?|{sep}.*)", sep=sep));
}
Token::RecursiveZeroOrMore => {
re.push_str(&format!("(?:{sep}|{sep}.*{sep})", sep=sep));
}
Token::Class { negated, ref ranges } => {
re.push('[');
if negated {
re.push('^');
}
for r in ranges {
if r.0 == r.1 {
// Not strictly necessary, but nicer to look at.
re.push_str(&regex::quote(&r.0.to_string()));
} else {
re.push_str(&regex::quote(&r.0.to_string()));
re.push('-');
re.push_str(&regex::quote(&r.1.to_string()));
}
}
re.push(']');
}
}
}
re.push('$');
re
}
}
struct Parser<'a> {
p: Pattern,
chars: iter::Peekable<str::Chars<'a>>,
prev: Option<char>,
cur: Option<char>,
}
impl<'a> Parser<'a> {
fn parse(&mut self) -> Result<(), Error> {
while let Some(c) = self.bump() {
match c {
'?' => self.p.tokens.push(Token::Any),
'*' => try!(self.parse_star()),
'[' => try!(self.parse_class()),
c => self.p.tokens.push(Token::Literal(c)),
}
}
Ok(())
}
fn parse_star(&mut self) -> Result<(), Error> {
let prev = self.prev;
if self.chars.peek() != Some(&'*') {
self.p.tokens.push(Token::ZeroOrMore);
return Ok(());
}
assert!(self.bump() == Some('*'));
if self.p.tokens.is_empty() {
self.p.tokens.push(Token::RecursivePrefix);
let next = self.bump();
if !next.is_none() && next != Some('/') {
return Err(Error::InvalidRecursive);
}
return Ok(());
}
let last = self.p.tokens.pop().unwrap();
if prev != Some('/') {
return Err(Error::InvalidRecursive);
}
let next = self.bump();
if next.is_none() {
self.p.tokens.push(Token::RecursiveSuffix);
return Ok(());
}
if next != Some('/') {
return Err(Error::InvalidRecursive);
}
self.p.tokens.push(Token::RecursiveZeroOrMore);
Ok(())
}
fn parse_class(&mut self) -> Result<(), Error> {
fn add_to_last_range(
r: &mut (char, char),
add: char,
) -> Result<(), Error> {
r.1 = add;
if r.1 < r.0 {
Err(Error::InvalidRange(r.0, r.1))
} else {
Ok(())
}
}
let mut negated = false;
let mut ranges = vec![];
if self.chars.peek() == Some(&'!') {
assert!(self.bump() == Some('!'));
negated = true;
}
let mut first = true;
let mut in_range = false;
loop {
let c = match self.bump() {
Some(c) => c,
// The only way to successfully break this loop is to observe
// a ']'.
None => return Err(Error::UnclosedClass),
};
match c {
']' => {
if first {
ranges.push((']', ']'));
} else {
break;
}
}
'-' => {
if first {
ranges.push(('-', '-'));
} else if in_range {
// invariant: in_range is only set when there is
// already at least one character seen.
let r = ranges.last_mut().unwrap();
try!(add_to_last_range(r, '-'));
in_range = false;
} else {
assert!(!ranges.is_empty());
in_range = true;
}
}
c => {
if in_range {
// invariant: in_range is only set when there is
// already at least one character seen.
try!(add_to_last_range(ranges.last_mut().unwrap(), c));
} else {
ranges.push((c, c));
}
in_range = false;
}
}
first = false;
}
if in_range {
// Means that the last character in the class was a '-', so add
// it as a literal.
ranges.push(('-', '-'));
}
self.p.tokens.push(Token::Class {
negated: negated,
ranges: ranges,
});
Ok(())
}
fn bump(&mut self) -> Option<char> {
self.prev = self.cur;
self.cur = self.chars.next();
self.cur
}
}
#[cfg(test)]
mod tests {
use std::path::Path;
use regex::bytes::Regex;
use super::{Error, Pattern, MatchOptions, SetBuilder, Token};
use super::Token::*;
macro_rules! syntax {
($name:ident, $pat:expr, $tokens:expr) => {
#[test]
fn $name() {
let pat = Pattern::new($pat).unwrap();
assert_eq!($tokens, pat.tokens);
}
}
}
macro_rules! syntaxerr {
($name:ident, $pat:expr, $err:expr) => {
#[test]
fn $name() {
let err = Pattern::new($pat).unwrap_err();
assert_eq!($err, err);
}
}
}
macro_rules! toregex {
($name:ident, $pat:expr, $re:expr) => {
toregex!($name, $pat, $re, MatchOptions::default());
};
($name:ident, $pat:expr, $re:expr, $options:expr) => {
#[test]
fn $name() {
let pat = Pattern::new($pat).unwrap();
assert_eq!(
format!("(?-u){}", $re), pat.to_regex_with(&$options));
}
};
}
macro_rules! matches {
($name:ident, $pat:expr, $path:expr) => {
matches!($name, $pat, $path, MatchOptions::default());
};
($name:ident, $pat:expr, $path:expr, $options:expr) => {
#[test]
fn $name() {
let pat = Pattern::new($pat).unwrap();
let path = &Path::new($path).to_str().unwrap();
let re = Regex::new(&pat.to_regex_with(&$options)).unwrap();
assert!(re.is_match(path.as_bytes()));
}
};
}
macro_rules! nmatches {
($name:ident, $pat:expr, $path:expr) => {
nmatches!($name, $pat, $path, MatchOptions::default());
};
($name:ident, $pat:expr, $path:expr, $options:expr) => {
#[test]
fn $name() {
let pat = Pattern::new($pat).unwrap();
let path = &Path::new($path).to_str().unwrap();
let re = Regex::new(&pat.to_regex_with(&$options)).unwrap();
assert!(!re.is_match(path.as_bytes()));
}
};
}
fn class(s: char, e: char) -> Token {
Class { negated: false, ranges: vec![(s, e)] }
}
fn classn(s: char, e: char) -> Token {
Class { negated: true, ranges: vec![(s, e)] }
}
fn rclass(ranges: &[(char, char)]) -> Token {
Class { negated: false, ranges: ranges.to_vec() }
}
fn rclassn(ranges: &[(char, char)]) -> Token {
Class { negated: true, ranges: ranges.to_vec() }
}
syntax!(literal1, "a", vec![Literal('a')]);
syntax!(literal2, "ab", vec![Literal('a'), Literal('b')]);
syntax!(any1, "?", vec![Any]);
syntax!(any2, "a?b", vec![Literal('a'), Any, Literal('b')]);
syntax!(seq1, "*", vec![ZeroOrMore]);
syntax!(seq2, "a*b", vec![Literal('a'), ZeroOrMore, Literal('b')]);
syntax!(seq3, "*a*b*", vec![
ZeroOrMore, Literal('a'), ZeroOrMore, Literal('b'), ZeroOrMore,
]);
syntax!(rseq1, "**", vec![RecursivePrefix]);
syntax!(rseq2, "**/", vec![RecursivePrefix]);
syntax!(rseq3, "/**", vec![RecursiveSuffix]);
syntax!(rseq4, "/**/", vec![RecursiveZeroOrMore]);
syntax!(rseq5, "a/**/b", vec![
Literal('a'), RecursiveZeroOrMore, Literal('b'),
]);
syntax!(cls1, "[a]", vec![class('a', 'a')]);
syntax!(cls2, "[!a]", vec![classn('a', 'a')]);
syntax!(cls3, "[a-z]", vec![class('a', 'z')]);
syntax!(cls4, "[!a-z]", vec![classn('a', 'z')]);
syntax!(cls5, "[-]", vec![class('-', '-')]);
syntax!(cls6, "[]]", vec![class(']', ']')]);
syntax!(cls7, "[*]", vec![class('*', '*')]);
syntax!(cls8, "[!!]", vec![classn('!', '!')]);
syntax!(cls9, "[a-]", vec![rclass(&[('a', 'a'), ('-', '-')])]);
syntax!(cls10, "[-a-z]", vec![rclass(&[('-', '-'), ('a', 'z')])]);
syntax!(cls11, "[a-z-]", vec![rclass(&[('a', 'z'), ('-', '-')])]);
syntax!(cls12, "[-a-z-]", vec![
rclass(&[('-', '-'), ('a', 'z'), ('-', '-')]),
]);
syntax!(cls13, "[]-z]", vec![class(']', 'z')]);
syntax!(cls14, "[--z]", vec![class('-', 'z')]);
syntax!(cls15, "[ --]", vec![class(' ', '-')]);
syntax!(cls16, "[0-9a-z]", vec![rclass(&[('0', '9'), ('a', 'z')])]);
syntax!(cls17, "[a-z0-9]", vec![rclass(&[('a', 'z'), ('0', '9')])]);
syntax!(cls18, "[!0-9a-z]", vec![rclassn(&[('0', '9'), ('a', 'z')])]);
syntax!(cls19, "[!a-z0-9]", vec![rclassn(&[('a', 'z'), ('0', '9')])]);
syntaxerr!(err_rseq1, "a**", Error::InvalidRecursive);
syntaxerr!(err_rseq2, "**a", Error::InvalidRecursive);
syntaxerr!(err_rseq3, "a**b", Error::InvalidRecursive);
syntaxerr!(err_rseq4, "***", Error::InvalidRecursive);
syntaxerr!(err_rseq5, "/a**", Error::InvalidRecursive);
syntaxerr!(err_rseq6, "/**a", Error::InvalidRecursive);
syntaxerr!(err_rseq7, "/a**b", Error::InvalidRecursive);
syntaxerr!(err_unclosed1, "[", Error::UnclosedClass);
syntaxerr!(err_unclosed2, "[]", Error::UnclosedClass);
syntaxerr!(err_unclosed3, "[!", Error::UnclosedClass);
syntaxerr!(err_unclosed4, "[!]", Error::UnclosedClass);
syntaxerr!(err_range1, "[z-a]", Error::InvalidRange('z', 'a'));
syntaxerr!(err_range2, "[z--]", Error::InvalidRange('z', '-'));
const SLASHLIT: MatchOptions = MatchOptions {
case_insensitive: false,
require_literal_separator: true,
};
const CASEI: MatchOptions = MatchOptions {
case_insensitive: true,
require_literal_separator: false,
};
const SEP: char = ::std::path::MAIN_SEPARATOR;
toregex!(re_casei, "a", "(?i)^a$", &CASEI);
toregex!(re_slash1, "?", format!("^[^{}]$", SEP), SLASHLIT);
toregex!(re_slash2, "*", format!("^[^{}]*$", SEP), SLASHLIT);
toregex!(re1, "a", "^a$");
toregex!(re2, "?", "^.$");
toregex!(re3, "*", "^.*$");
toregex!(re4, "a?", "^a.$");
toregex!(re5, "?a", "^.a$");
toregex!(re6, "a*", "^a.*$");
toregex!(re7, "*a", "^.*a$");
toregex!(re8, "[*]", r"^[\*]$");
toregex!(re9, "[+]", r"^[\+]$");
toregex!(re10, "+", r"^\+$");
toregex!(re11, "**", r"^.*$");
matches!(match1, "a", "a");
matches!(match2, "a*b", "a_b");
matches!(match3, "a*b*c", "abc");
matches!(match4, "a*b*c", "a_b_c");
matches!(match5, "a*b*c", "a___b___c");
matches!(match6, "abc*abc*abc", "abcabcabcabcabcabcabc");
matches!(match7, "a*a*a*a*a*a*a*a*a", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
matches!(match8, "a*b[xyz]c*d", "abxcdbxcddd");
matches!(matchrec1, "some/**/needle.txt", "some/needle.txt");
matches!(matchrec2, "some/**/needle.txt", "some/one/needle.txt");
matches!(matchrec3, "some/**/needle.txt", "some/one/two/needle.txt");
matches!(matchrec4, "some/**/needle.txt", "some/other/needle.txt");
matches!(matchrec5, "**", "abcde");
matches!(matchrec6, "**", "");
matches!(matchrec7, "**", ".asdf");
matches!(matchrec8, "**", "/x/.asdf");
matches!(matchrec9, "some/**/**/needle.txt", "some/needle.txt");
matches!(matchrec10, "some/**/**/needle.txt", "some/one/needle.txt");
matches!(matchrec11, "some/**/**/needle.txt", "some/one/two/needle.txt");
matches!(matchrec12, "some/**/**/needle.txt", "some/other/needle.txt");
matches!(matchrec13, "**/test", "one/two/test");
matches!(matchrec14, "**/test", "one/test");
matches!(matchrec15, "**/test", "test");
matches!(matchrec16, "/**/test", "/one/two/test");
matches!(matchrec17, "/**/test", "/one/test");
matches!(matchrec18, "/**/test", "/test");
matches!(matchrec19, "**/.*", ".abc");
matches!(matchrec20, "**/.*", "abc/.abc");
matches!(matchrec21, ".*/**", ".abc");
matches!(matchrec22, ".*/**", ".abc/abc");
matches!(matchrange1, "a[0-9]b", "a0b");
matches!(matchrange2, "a[0-9]b", "a9b");
matches!(matchrange3, "a[!0-9]b", "a_b");
matches!(matchrange4, "[a-z123]", "1");
matches!(matchrange5, "[1a-z23]", "1");
matches!(matchrange6, "[123a-z]", "1");
matches!(matchrange7, "[abc-]", "-");
matches!(matchrange8, "[-abc]", "-");
matches!(matchrange9, "[-a-c]", "b");
matches!(matchrange10, "[a-c-]", "b");
matches!(matchrange11, "[-]", "-");
matches!(matchpat1, "*hello.txt", "hello.txt");
matches!(matchpat2, "*hello.txt", "gareth_says_hello.txt");
matches!(matchpat3, "*hello.txt", "some/path/to/hello.txt");
matches!(matchpat4, "*hello.txt", "some\\path\\to\\hello.txt");
matches!(matchpat5, "*hello.txt", "/an/absolute/path/to/hello.txt");
matches!(matchpat6, "*some/path/to/hello.txt", "some/path/to/hello.txt");
matches!(matchpat7, "*some/path/to/hello.txt",
"a/bigger/some/path/to/hello.txt");
matches!(matchescape, "_[[]_[]]_[?]_[*]_!_", "_[_]_?_*_!_");
matches!(matchcasei1, "aBcDeFg", "aBcDeFg", CASEI);
matches!(matchcasei2, "aBcDeFg", "abcdefg", CASEI);
matches!(matchcasei3, "aBcDeFg", "ABCDEFG", CASEI);
matches!(matchcasei4, "aBcDeFg", "AbCdEfG", CASEI);
matches!(matchslash1, "abc/def", "abc/def", SLASHLIT);
nmatches!(matchslash2, "abc?def", "abc/def", SLASHLIT);
nmatches!(matchslash3, "abc*def", "abc/def", SLASHLIT);
matches!(matchslash4, "abc[/]def", "abc/def", SLASHLIT); // differs
nmatches!(matchnot1, "a*b*c", "abcd");
nmatches!(matchnot2, "abc*abc*abc", "abcabcabcabcabcabcabca");
nmatches!(matchnot3, "some/**/needle.txt", "some/other/notthis.txt");
nmatches!(matchnot4, "some/**/**/needle.txt", "some/other/notthis.txt");
nmatches!(matchnot5, "/**/test", "test");
nmatches!(matchnot6, "/**/test", "/one/notthis");
nmatches!(matchnot7, "/**/test", "/notthis");
nmatches!(matchnot8, "**/.*", "ab.c");
nmatches!(matchnot9, "**/.*", "abc/ab.c");
nmatches!(matchnot10, ".*/**", "a.bc");
nmatches!(matchnot11, ".*/**", "abc/a.bc");
nmatches!(matchnot12, "a[0-9]b", "a_b");
nmatches!(matchnot13, "a[!0-9]b", "a0b");
nmatches!(matchnot14, "a[!0-9]b", "a9b");
nmatches!(matchnot15, "[!-]", "-");
nmatches!(matchnot16, "*hello.txt", "hello.txt-and-then-some");
nmatches!(matchnot17, "*hello.txt", "goodbye.txt");
nmatches!(matchnot18, "*some/path/to/hello.txt",
"some/path/to/hello.txt-and-then-some");
nmatches!(matchnot19, "*some/path/to/hello.txt",
"some/other/path/to/hello.txt");
#[test]
fn set_works() {
let mut builder = SetBuilder::new();
builder.add("src/**/*.rs").unwrap();
builder.add("*.c").unwrap();
builder.add("src/lib.rs").unwrap();
let set = builder.build().unwrap();
assert!(set.is_match("foo.c"));
assert!(set.is_match("src/foo.c"));
assert!(!set.is_match("foo.rs"));
assert!(!set.is_match("tests/foo.rs"));
assert!(set.is_match("src/foo.rs"));
assert!(set.is_match("src/grep/src/main.rs"));
assert_eq!(2, set.matches("src/lib.rs").iter().count());
assert!(set.matches("src/lib.rs").matched(0));
assert!(!set.matches("src/lib.rs").matched(1));
assert!(set.matches("src/lib.rs").matched(2));
}
}

View File

@@ -5,7 +5,7 @@ whether a *single* file path should be searched or not.
In general, there are two ways to ignore a particular file:
1. Specify an ignore rule in some "global" configuration, such as a
$HOME/.xrepignore or on the command line.
$HOME/.ignore or on the command line.
2. A specific ignore file (like .gitignore) found during directory traversal.
The `IgnoreDir` type handles ignore patterns for any one particular directory
@@ -14,17 +14,19 @@ of `IgnoreDir`s for use during directory traversal.
*/
use std::error::Error as StdError;
use std::ffi::OsString;
use std::fmt;
use std::io;
use std::path::{Path, PathBuf};
use gitignore::{self, Gitignore, GitignoreBuilder, Match, Pattern};
use pathutil::{file_name, is_hidden};
use types::Types;
const IGNORE_NAMES: &'static [&'static str] = &[
".gitignore",
".agignore",
".xrepignore",
".ignore",
".rgignore",
];
/// Represents an error that can occur when parsing a gitignore file.
@@ -77,14 +79,21 @@ impl From<gitignore::Error> for Error {
pub struct Ignore {
/// A stack of ignore patterns at each directory level of traversal.
/// A directory that contributes no ignore patterns is `None`.
stack: Vec<Option<IgnoreDir>>,
stack: Vec<IgnoreDir>,
/// A stack of parent directories above the root of the current search.
parent_stack: Vec<IgnoreDir>,
/// A set of override globs that are always checked first. A match (whether
/// it's whitelist or blacklist) trumps anything in stack.
overrides: Overrides,
/// A file type matcher.
types: Types,
/// Whether to ignore hidden files or not.
ignore_hidden: bool,
/// When true, don't look at .gitignore or .ignore files for ignore
/// rules.
no_ignore: bool,
/// When true, don't look at .gitignore files for ignore rules.
no_ignore_vcs: bool,
}
impl Ignore {
@@ -92,10 +101,12 @@ impl Ignore {
pub fn new() -> Ignore {
Ignore {
stack: vec![],
parent_stack: vec![],
overrides: Overrides::new(None),
types: Types::empty(),
ignore_hidden: true,
no_ignore: false,
no_ignore_vcs: true,
}
}
@@ -111,6 +122,12 @@ impl Ignore {
self
}
/// When set, VCS ignore files are ignored.
pub fn no_ignore_vcs(&mut self, yes: bool) -> &mut Ignore {
self.no_ignore_vcs = yes;
self
}
/// Add a set of globs that overrides all other match logic.
pub fn add_override(&mut self, gi: Gitignore) -> &mut Ignore {
self.overrides = Overrides::new(Some(gi));
@@ -135,10 +152,13 @@ impl Ignore {
let mut path = &*path;
let mut saw_git = path.join(".git").is_dir();
let mut ignore_names = IGNORE_NAMES.to_vec();
if self.no_ignore_vcs {
ignore_names.retain(|&name| name != ".gitignore");
}
let mut ignore_dir_results = vec![];
while let Some(parent) = path.parent() {
if self.no_ignore {
ignore_dir_results.push(Ok(None));
ignore_dir_results.push(Ok(IgnoreDir::empty(parent)));
} else {
if saw_git {
ignore_names.retain(|&name| name != ".gitignore");
@@ -153,7 +173,7 @@ impl Ignore {
}
for ignore_dir_result in ignore_dir_results.into_iter().rev() {
try!(self.push_ignore_dir(ignore_dir_result));
self.parent_stack.push(try!(ignore_dir_result));
}
Ok(())
}
@@ -164,10 +184,13 @@ impl Ignore {
/// stack (and therefore should be popped).
pub fn push<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error> {
if self.no_ignore {
self.stack.push(None);
return Ok(());
self.stack.push(IgnoreDir::empty(path));
Ok(())
} else if self.no_ignore_vcs {
self.push_ignore_dir(IgnoreDir::without_vcs(path))
} else {
self.push_ignore_dir(IgnoreDir::new(path))
}
self.push_ignore_dir(IgnoreDir::new(path))
}
/// Pushes the result of building a directory matcher on to the stack.
@@ -175,7 +198,7 @@ impl Ignore {
/// If the result given contains an error, then it is returned.
pub fn push_ignore_dir(
&mut self,
result: Result<Option<IgnoreDir>, Error>,
result: Result<IgnoreDir, Error>,
) -> Result<(), Error> {
match result {
Ok(id) => {
@@ -184,7 +207,7 @@ impl Ignore {
}
Err(err) => {
// Don't leave the stack in an inconsistent state.
self.stack.push(None);
self.stack.push(IgnoreDir::empty("error"));
Err(err)
}
}
@@ -204,24 +227,53 @@ impl Ignore {
if let Some(is_ignored) = self.ignore_match(path, mat) {
return is_ignored;
}
if self.ignore_hidden && is_hidden(&path) {
debug!("{} ignored because it is hidden", path.display());
return true;
}
for id in self.stack.iter().rev().filter_map(|id| id.as_ref()) {
let mat = id.matched(path, is_dir);
if let Some(is_ignored) = self.ignore_match(path, mat) {
if is_ignored {
return true;
let mut whitelisted = false;
if !self.no_ignore {
for id in self.stack.iter().rev() {
let mat = id.matched(path, is_dir);
if let Some(is_ignored) = self.ignore_match(path, mat) {
if is_ignored {
return true;
}
// If this path is whitelisted by an ignore, then
// fallthrough and let the file type matcher have a say.
whitelisted = true;
break;
}
}
// If the file has been whitelisted, then we have to stop checking
// parent directories. The only thing that can override a whitelist
// at this point is a type filter.
if !whitelisted {
let mut path = path.to_path_buf();
for id in self.parent_stack.iter().rev() {
if let Some(ref dirname) = id.name {
path = Path::new(dirname).join(path);
}
let mat = id.matched(&*path, is_dir);
if let Some(is_ignored) = self.ignore_match(&*path, mat) {
if is_ignored {
return true;
}
// If this path is whitelisted by an ignore, then
// fallthrough and let the file type matcher have a
// say.
whitelisted = true;
break;
}
}
// If this path is whitelisted by an ignore, then fallthrough
// and let the file type matcher have a say.
break;
}
}
let mat = self.types.matched(path, is_dir);
if let Some(is_ignored) = self.ignore_match(path, mat) {
return is_ignored;
if is_ignored {
return true;
}
whitelisted = true;
}
if !whitelisted && self.ignore_hidden && is_hidden(&path) {
debug!("{} ignored because it is hidden", path.display());
return true;
}
false
}
@@ -251,14 +303,17 @@ impl Ignore {
/// IgnoreDir represents a set of ignore patterns retrieved from a single
/// directory.
#[derive(Debug)]
pub struct IgnoreDir {
/// The path to this directory as given.
path: PathBuf,
/// The directory name, if one exists.
name: Option<OsString>,
/// A single accumulation of glob patterns for this directory, matched
/// using gitignore semantics.
///
/// This will include patterns from xrepignore as well. The patterns are
/// ordered so that precedence applies automatically (e.g., xrepignore
/// This will include patterns from rgignore as well. The patterns are
/// ordered so that precedence applies automatically (e.g., rgignore
/// patterns procede gitignore patterns).
gi: Option<Gitignore>,
// TODO(burntsushi): Matching other types of glob patterns that don't
@@ -267,13 +322,27 @@ pub struct IgnoreDir {
impl IgnoreDir {
/// Create a new matcher for the given directory.
///
/// If no ignore glob patterns could be found in the directory then `None`
/// is returned.
pub fn new<P: AsRef<Path>>(path: P) -> Result<Option<IgnoreDir>, Error> {
pub fn new<P: AsRef<Path>>(path: P) -> Result<IgnoreDir, Error> {
IgnoreDir::with_ignore_names(path, IGNORE_NAMES.iter())
}
/// Create a new matcher for the given directory.
///
/// Don't respect VCS ignore files.
pub fn without_vcs<P: AsRef<Path>>(path: P) -> Result<IgnoreDir, Error> {
let names = IGNORE_NAMES.iter().filter(|name| **name != ".gitignore");
IgnoreDir::with_ignore_names(path, names)
}
/// Create a new IgnoreDir that never matches anything with the given path.
pub fn empty<P: AsRef<Path>>(path: P) -> IgnoreDir {
IgnoreDir {
path: path.as_ref().to_path_buf(),
name: file_name(path.as_ref()).map(|s| s.to_os_string()),
gi: None,
}
}
/// Create a new matcher for the given directory using only the ignore
/// patterns found in the file names given.
///
@@ -286,12 +355,9 @@ impl IgnoreDir {
pub fn with_ignore_names<P: AsRef<Path>, S, I>(
path: P,
names: I,
) -> Result<Option<IgnoreDir>, Error>
) -> Result<IgnoreDir, Error>
where P: AsRef<Path>, S: AsRef<str>, I: Iterator<Item=S> {
let mut id = IgnoreDir {
path: path.as_ref().to_path_buf(),
gi: None,
};
let mut id = IgnoreDir::empty(path);
let mut ok = false;
let mut builder = GitignoreBuilder::new(&id.path);
// The ordering here is important. Later globs have higher precedence.
@@ -299,11 +365,10 @@ impl IgnoreDir {
ok = builder.add_path(id.path.join(name.as_ref())).is_ok() || ok;
}
if !ok {
Ok(None)
} else {
id.gi = Some(try!(builder.build()));
Ok(Some(id))
return Ok(id);
}
id.gi = Some(try!(builder.build()));
Ok(id)
}
/// Returns true if and only if the given file path should be ignored
@@ -354,15 +419,10 @@ impl Overrides {
/// Match::None (and interpreting non-matches as ignored) unless is_dir
/// is true.
pub fn matched<P: AsRef<Path>>(&self, path: P, is_dir: bool) -> Match {
// File types don't apply to directories.
if is_dir {
return Match::None;
}
let path = path.as_ref();
self.gi.as_ref()
.map(|gi| {
let path = &*path.to_string_lossy();
let mat = gi.matched_utf8(path, is_dir).invert();
let mat = gi.matched_stripped(path, is_dir).invert();
if mat.is_none() && !is_dir {
if gi.num_ignores() > 0 {
return Match::Ignored(&self.unmatched_pat);
@@ -374,14 +434,6 @@ impl Overrides {
}
}
fn is_hidden<P: AsRef<Path>>(path: P) -> bool {
if let Some(name) = path.as_ref().file_name() {
name.to_str().map(|s| s.starts_with(".")).unwrap_or(false)
} else {
false
}
}
#[cfg(test)]
mod tests {
use std::path::Path;
@@ -398,6 +450,9 @@ mod tests {
let gi = builder.build().unwrap();
let id = IgnoreDir {
path: Path::new($root).to_path_buf(),
name: Path::new($root).file_name().map(|s| {
s.to_os_string()
}),
gi: Some(gi),
};
assert!(id.matched($path, false).is_ignored());
@@ -415,6 +470,9 @@ mod tests {
let gi = builder.build().unwrap();
let id = IgnoreDir {
path: Path::new($root).to_path_buf(),
name: Path::new($root).file_name().map(|s| {
s.to_os_string()
}),
gi: Some(gi),
};
assert!(!id.matched($path, false).is_ignored());
@@ -422,7 +480,7 @@ mod tests {
};
}
const ROOT: &'static str = "/home/foobar/rust/xrep";
const ROOT: &'static str = "/home/foobar/rust/rg";
ignored_dir!(id1, ROOT, "src/main.rs", "", "src/main.rs");
ignored_dir!(id2, ROOT, "", "src/main.rs", "src/main.rs");

View File

@@ -1,8 +1,7 @@
#![allow(dead_code, unused_variables)]
extern crate crossbeam;
extern crate deque;
extern crate docopt;
extern crate env_logger;
extern crate globset;
extern crate grep;
#[cfg(windows)]
extern crate kernel32;
@@ -15,7 +14,6 @@ extern crate memchr;
extern crate memmap;
extern crate num_cpus;
extern crate regex;
extern crate regex_syntax as syntax;
extern crate rustc_serialize;
extern crate term;
extern crate thread_local;
@@ -30,16 +28,23 @@ use std::path::Path;
use std::process;
use std::result;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::cmp;
use crossbeam::sync::chase_lev::{self, Steal, Stealer};
use deque::{Stealer, Stolen};
use grep::Grep;
use memmap::{Mmap, Protection};
use term::Terminal;
use walkdir::DirEntry;
use args::Args;
use out::Out;
use out::{ColoredTerminal, Out};
use pathutil::strip_prefix;
use printer::Printer;
use search::InputBuffer;
use search_stream::InputBuffer;
#[cfg(windows)]
use terminal_win::WindowsBuffer;
macro_rules! errored {
($($tt:tt)*) => {
@@ -55,14 +60,16 @@ macro_rules! eprintln {
}
mod args;
mod atty;
mod gitignore;
mod glob;
mod ignore;
mod out;
mod pathutil;
mod printer;
mod search;
mod sys;
mod terminal;
mod search_buffer;
mod search_stream;
#[cfg(windows)]
mod terminal_win;
mod types;
mod walk;
@@ -71,7 +78,7 @@ pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;
fn main() {
match Args::parse().and_then(run) {
Ok(count) if count == 0 => process::exit(1),
Ok(count) => process::exit(0),
Ok(_) => process::exit(0),
Err(err) => {
eprintln!("{}", err);
process::exit(1);
@@ -80,41 +87,67 @@ fn main() {
}
fn run(args: Args) -> Result<u64> {
let args = Arc::new(args);
let paths = args.paths();
let threads = cmp::max(1, args.threads() - 1);
let isone =
paths.len() == 1 && (paths[0] == Path::new("-") || paths[0].is_file());
if args.files() {
return run_files(args);
return run_files(args.clone());
}
if args.type_list() {
return run_types(args);
return run_types(args.clone());
}
let args = Arc::new(args);
let out = Arc::new(Mutex::new(args.out(io::stdout())));
if threads == 1 || isone {
return run_one_thread(args.clone());
}
let out = Arc::new(Mutex::new(args.out()));
let quiet_matched = QuietMatched::new(args.quiet());
let mut workers = vec![];
let mut workq = {
let (workq, stealer) = chase_lev::deque();
for _ in 0..args.threads() {
let worker = Worker {
args: args.clone(),
out: out.clone(),
let workq = {
let (workq, stealer) = deque::new();
for _ in 0..threads {
let worker = MultiWorker {
chan_work: stealer.clone(),
inpbuf: args.input_buffer(),
outbuf: Some(vec![]),
grep: try!(args.grep()),
match_count: 0,
quiet_matched: quiet_matched.clone(),
out: out.clone(),
outbuf: Some(args.outbuf()),
worker: Worker {
args: args.clone(),
inpbuf: args.input_buffer(),
grep: args.grep(),
match_count: 0,
},
};
workers.push(thread::spawn(move || worker.run()));
}
workq
};
for p in args.paths() {
let mut paths_searched: u64 = 0;
for p in paths {
if quiet_matched.has_match() {
break;
}
if p == Path::new("-") {
workq.push(Work::Stdin)
paths_searched += 1;
workq.push(Work::Stdin);
} else {
for ent in try!(args.walker(p)) {
if quiet_matched.has_match() {
break;
}
paths_searched += 1;
workq.push(Work::File(ent));
}
}
}
if !paths.is_empty() && paths_searched == 0 {
eprintln!("No files were searched, which means ripgrep probably \
applied a filter you didn't expect. \
Try running again with --debug.");
}
for _ in 0..workers.len() {
workq.push(Work::Quit);
}
@@ -125,8 +158,64 @@ fn run(args: Args) -> Result<u64> {
Ok(match_count)
}
fn run_files(args: Args) -> Result<u64> {
let mut printer = args.printer(io::BufWriter::new(io::stdout()));
fn run_one_thread(args: Arc<Args>) -> Result<u64> {
let mut worker = Worker {
args: args.clone(),
inpbuf: args.input_buffer(),
grep: args.grep(),
match_count: 0,
};
let paths = args.paths();
let mut term = args.stdout();
let mut paths_searched: u64 = 0;
for p in paths {
if args.quiet() && worker.match_count > 0 {
break;
}
if p == Path::new("-") {
paths_searched += 1;
let mut printer = args.printer(&mut term);
if worker.match_count > 0 {
if let Some(sep) = args.file_separator() {
printer = printer.file_separator(sep);
}
}
worker.do_work(&mut printer, WorkReady::Stdin);
} else {
for ent in try!(args.walker(p)) {
paths_searched += 1;
let mut printer = args.printer(&mut term);
if worker.match_count > 0 {
if args.quiet() {
break;
}
if let Some(sep) = args.file_separator() {
printer = printer.file_separator(sep);
}
}
let file = match File::open(ent.path()) {
Ok(file) => file,
Err(err) => {
eprintln!("{}: {}", ent.path().display(), err);
continue;
}
};
worker.do_work(&mut printer, WorkReady::DirFile(ent, file));
}
}
}
if !paths.is_empty() && paths_searched == 0 {
eprintln!("No files were searched, which means ripgrep probably \
applied a filter you didn't expect. \
Try running again with --debug.");
}
Ok(worker.match_count)
}
fn run_files(args: Arc<Args>) -> Result<u64> {
let term = args.stdout();
let mut printer = args.printer(term);
let mut file_count = 0;
for p in args.paths() {
if p == Path::new("-") {
@@ -142,8 +231,9 @@ fn run_files(args: Args) -> Result<u64> {
Ok(file_count)
}
fn run_types(args: Args) -> Result<u64> {
let mut printer = args.printer(io::BufWriter::new(io::stdout()));
fn run_types(args: Arc<Args>) -> Result<u64> {
let term = args.stdout();
let mut printer = args.printer(term);
let mut ty_count = 0;
for def in args.type_defs() {
printer.type_def(def);
@@ -160,30 +250,40 @@ enum Work {
enum WorkReady {
Stdin,
File(DirEntry, File),
DirFile(DirEntry, File),
}
struct MultiWorker {
chan_work: Stealer<Work>,
quiet_matched: QuietMatched,
out: Arc<Mutex<Out>>,
#[cfg(not(windows))]
outbuf: Option<ColoredTerminal<term::TerminfoTerminal<Vec<u8>>>>,
#[cfg(windows)]
outbuf: Option<ColoredTerminal<WindowsBuffer>>,
worker: Worker,
}
struct Worker {
args: Arc<Args>,
out: Arc<Mutex<Out<io::Stdout>>>,
chan_work: Stealer<Work>,
inpbuf: InputBuffer,
outbuf: Option<Vec<u8>>,
grep: Grep,
match_count: u64,
}
impl Worker {
impl MultiWorker {
fn run(mut self) -> u64 {
self.match_count = 0;
loop {
if self.quiet_matched.has_match() {
break;
}
let work = match self.chan_work.steal() {
Steal::Empty | Steal::Abort => continue,
Steal::Data(Work::Quit) => break,
Steal::Data(Work::Stdin) => WorkReady::Stdin,
Steal::Data(Work::File(ent)) => {
Stolen::Empty | Stolen::Abort => continue,
Stolen::Data(Work::Quit) => break,
Stolen::Data(Work::Stdin) => WorkReady::Stdin,
Stolen::Data(Work::File(ent)) => {
match File::open(ent.path()) {
Ok(file) => WorkReady::File(ent, file),
Ok(file) => WorkReady::DirFile(ent, file),
Err(err) => {
eprintln!("{}: {}", ent.path().display(), err);
continue;
@@ -193,19 +293,24 @@ impl Worker {
};
let mut outbuf = self.outbuf.take().unwrap();
outbuf.clear();
let mut printer = self.args.printer(outbuf);
self.do_work(&mut printer, work);
let mut printer = self.worker.args.printer(outbuf);
self.worker.do_work(&mut printer, work);
if self.quiet_matched.set_match(self.worker.match_count > 0) {
break;
}
let outbuf = printer.into_inner();
if !outbuf.is_empty() {
if !outbuf.get_ref().is_empty() {
let mut out = self.out.lock().unwrap();
out.write(&outbuf);
}
self.outbuf = Some(outbuf);
}
self.match_count
self.worker.match_count
}
}
fn do_work<W: Send + io::Write>(
impl Worker {
fn do_work<W: Terminal + Send>(
&mut self,
printer: &mut Printer<W>,
work: WorkReady,
@@ -216,12 +321,16 @@ impl Worker {
let stdin = stdin.lock();
self.search(printer, &Path::new("<stdin>"), stdin)
}
WorkReady::File(ent, file) => {
WorkReady::DirFile(ent, file) => {
let mut path = ent.path();
if let Ok(p) = path.strip_prefix("./") {
if let Some(p) = strip_prefix("./", path) {
path = p;
}
self.search(printer, path, file)
if self.args.mmap() {
self.search_mmap(printer, path, &file)
} else {
self.search(printer, path, file)
}
}
};
match result {
@@ -234,7 +343,7 @@ impl Worker {
}
}
fn search<R: io::Read, W: Send + io::Write>(
fn search<R: io::Read, W: Terminal + Send>(
&mut self,
printer: &mut Printer<W>,
path: &Path,
@@ -248,4 +357,52 @@ impl Worker {
rdr,
).run().map_err(From::from)
}
fn search_mmap<W: Terminal + Send>(
&mut self,
printer: &mut Printer<W>,
path: &Path,
file: &File,
) -> Result<u64> {
if try!(file.metadata()).len() == 0 {
// Opening a memory map with an empty file results in an error.
// However, this may not actually be an empty file! For example,
// /proc/cpuinfo reports itself as an empty file, but it can
// produce data when it's read from. Therefore, we fall back to
// regular read calls.
return self.search(printer, path, file);
}
let mmap = try!(Mmap::open(file, Protection::Read));
Ok(self.args.searcher_buffer(
printer,
&self.grep,
path,
unsafe { mmap.as_slice() },
).run())
}
}
#[derive(Clone, Debug)]
struct QuietMatched(Arc<Option<AtomicBool>>);
impl QuietMatched {
fn new(quiet: bool) -> QuietMatched {
let atomic = if quiet { Some(AtomicBool::new(false)) } else { None };
QuietMatched(Arc::new(atomic))
}
fn has_match(&self) -> bool {
match *self.0 {
None => false,
Some(ref matched) => matched.load(Ordering::SeqCst),
}
}
fn set_match(&self, yes: bool) -> bool {
match *self.0 {
None => false,
Some(_) if !yes => false,
Some(ref m) => { m.store(true, Ordering::SeqCst); true }
}
}
}

View File

@@ -1,22 +1,46 @@
use std::io::{self, Write};
use term::{self, Terminal};
#[cfg(not(windows))]
use term::terminfo::TermInfo;
#[cfg(windows)]
use term::WinConsole;
#[cfg(windows)]
use terminal_win::WindowsBuffer;
/// Out controls the actual output of all search results for a particular file
/// to the end user.
///
/// (The difference between Out and Printer is that a Printer works with
/// individual search results where as Out works with search results for each
/// file as a whole. For example, it knows when to print a file separator.)
pub struct Out<W: io::Write> {
wtr: io::BufWriter<W>,
pub struct Out {
#[cfg(not(windows))]
term: ColoredTerminal<term::TerminfoTerminal<io::BufWriter<io::Stdout>>>,
#[cfg(windows)]
term: ColoredTerminal<WinConsole<io::Stdout>>,
printed: bool,
file_separator: Option<Vec<u8>>,
}
impl<W: io::Write> Out<W> {
impl Out {
/// Create a new Out that writes to the wtr given.
pub fn new(wtr: W) -> Out<W> {
#[cfg(not(windows))]
pub fn new(color: bool) -> Out {
let wtr = io::BufWriter::new(io::stdout());
Out {
wtr: io::BufWriter::new(wtr),
term: ColoredTerminal::new(wtr, color),
printed: false,
file_separator: None,
}
}
/// Create a new Out that writes to the wtr given.
#[cfg(windows)]
pub fn new(color: bool) -> Out {
Out {
term: ColoredTerminal::new_stdout(color),
printed: false,
file_separator: None,
}
@@ -24,24 +48,327 @@ impl<W: io::Write> Out<W> {
/// If set, the separator is printed between matches from different files.
/// By default, no separator is printed.
///
/// If sep is empty, then no file separator is printed.
pub fn file_separator(mut self, sep: Vec<u8>) -> Out<W> {
pub fn file_separator(mut self, sep: Vec<u8>) -> Out {
self.file_separator = Some(sep);
self
}
/// Write the search results of a single file to the underlying wtr and
/// flush wtr.
pub fn write(&mut self, buf: &[u8]) {
if let Some(ref sep) = self.file_separator {
if self.printed {
let _ = self.wtr.write_all(sep);
let _ = self.wtr.write_all(b"\n");
#[cfg(not(windows))]
pub fn write(
&mut self,
buf: &ColoredTerminal<term::TerminfoTerminal<Vec<u8>>>,
) {
self.write_sep();
match *buf {
ColoredTerminal::Colored(ref tt) => {
let _ = self.term.write_all(tt.get_ref());
}
ColoredTerminal::NoColor(ref buf) => {
let _ = self.term.write_all(buf);
}
}
let _ = self.wtr.write_all(buf);
let _ = self.wtr.flush();
self.write_done();
}
/// Write the search results of a single file to the underlying wtr and
/// flush wtr.
#[cfg(windows)]
pub fn write(
&mut self,
buf: &ColoredTerminal<WindowsBuffer>,
) {
self.write_sep();
match *buf {
ColoredTerminal::Colored(ref tt) => {
tt.print_stdout(&mut self.term);
}
ColoredTerminal::NoColor(ref buf) => {
let _ = self.term.write_all(buf);
}
}
self.write_done();
}
fn write_sep(&mut self) {
if let Some(ref sep) = self.file_separator {
if self.printed {
let _ = self.term.write_all(sep);
let _ = self.term.write_all(b"\n");
}
}
}
fn write_done(&mut self) {
let _ = self.term.flush();
self.printed = true;
}
}
/// ColoredTerminal provides optional colored output through the term::Terminal
/// trait. In particular, it will dynamically configure itself to use coloring
/// if it's available in the environment.
#[derive(Clone, Debug)]
pub enum ColoredTerminal<T: Terminal + Send> {
Colored(T),
NoColor(T::Output),
}
#[cfg(not(windows))]
impl<W: io::Write + Send> ColoredTerminal<term::TerminfoTerminal<W>> {
/// Create a new output buffer.
///
/// When color is true, the buffer will attempt to support coloring.
pub fn new(wtr: W, color: bool) -> Self {
lazy_static! {
// Only pay for parsing the terminfo once.
static ref TERMINFO: Option<TermInfo> = {
match TermInfo::from_env() {
Ok(info) => Some(info),
Err(err) => {
debug!("error loading terminfo for coloring: {}", err);
None
}
}
};
}
// If we want color, build a term::TerminfoTerminal and see if the
// current environment supports coloring. If not, bail with NoColor. To
// avoid losing our writer (ownership), do this the long way.
if !color {
return ColoredTerminal::NoColor(wtr);
}
let terminfo = match *TERMINFO {
None => return ColoredTerminal::NoColor(wtr),
Some(ref ti) => {
// Ug, this should go away with the next release of `term`.
TermInfo {
names: ti.names.clone(),
bools: ti.bools.clone(),
numbers: ti.numbers.clone(),
strings: ti.strings.clone(),
}
}
};
let tt = term::TerminfoTerminal::new_with_terminfo(wtr, terminfo);
if !tt.supports_color() {
debug!("environment doesn't support coloring");
return ColoredTerminal::NoColor(tt.into_inner());
}
ColoredTerminal::Colored(tt)
}
}
#[cfg(not(windows))]
impl ColoredTerminal<term::TerminfoTerminal<Vec<u8>>> {
/// Clear the give buffer of all search results such that it is reusable
/// in another search.
pub fn clear(&mut self) {
match *self {
ColoredTerminal::Colored(ref mut tt) => {
tt.get_mut().clear();
}
ColoredTerminal::NoColor(ref mut buf) => {
buf.clear();
}
}
}
}
#[cfg(windows)]
impl ColoredTerminal<WindowsBuffer> {
/// Create a new output buffer.
///
/// When color is true, the buffer will attempt to support coloring.
pub fn new_buffer(color: bool) -> Self {
if !color {
ColoredTerminal::NoColor(vec![])
} else {
ColoredTerminal::Colored(WindowsBuffer::new())
}
}
/// Clear the give buffer of all search results such that it is reusable
/// in another search.
pub fn clear(&mut self) {
match *self {
ColoredTerminal::Colored(ref mut win) => win.clear(),
ColoredTerminal::NoColor(ref mut buf) => buf.clear(),
}
}
}
#[cfg(windows)]
impl ColoredTerminal<WinConsole<io::Stdout>> {
/// Create a new output buffer.
///
/// When color is true, the buffer will attempt to support coloring.
pub fn new_stdout(color: bool) -> Self {
if !color {
return ColoredTerminal::NoColor(io::stdout());
}
match WinConsole::new(io::stdout()) {
Ok(win) => ColoredTerminal::Colored(win),
Err(_) => ColoredTerminal::NoColor(io::stdout()),
}
}
}
impl<T: Terminal + Send> ColoredTerminal<T> {
fn map_result<F>(
&mut self,
mut f: F,
) -> term::Result<()>
where F: FnMut(&mut T) -> term::Result<()> {
match *self {
ColoredTerminal::Colored(ref mut w) => f(w),
ColoredTerminal::NoColor(_) => Err(term::Error::NotSupported),
}
}
fn map_bool<F>(
&self,
mut f: F,
) -> bool
where F: FnMut(&T) -> bool {
match *self {
ColoredTerminal::Colored(ref w) => f(w),
ColoredTerminal::NoColor(_) => false,
}
}
}
impl<T: Terminal + Send> io::Write for ColoredTerminal<T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match *self {
ColoredTerminal::Colored(ref mut w) => w.write(buf),
ColoredTerminal::NoColor(ref mut w) => w.write(buf),
}
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl<T: Terminal + Send> term::Terminal for ColoredTerminal<T> {
type Output = T::Output;
fn fg(&mut self, fg: term::color::Color) -> term::Result<()> {
self.map_result(|w| w.fg(fg))
}
fn bg(&mut self, bg: term::color::Color) -> term::Result<()> {
self.map_result(|w| w.bg(bg))
}
fn attr(&mut self, attr: term::Attr) -> term::Result<()> {
self.map_result(|w| w.attr(attr))
}
fn supports_attr(&self, attr: term::Attr) -> bool {
self.map_bool(|w| w.supports_attr(attr))
}
fn reset(&mut self) -> term::Result<()> {
self.map_result(|w| w.reset())
}
fn supports_reset(&self) -> bool {
self.map_bool(|w| w.supports_reset())
}
fn supports_color(&self) -> bool {
self.map_bool(|w| w.supports_color())
}
fn cursor_up(&mut self) -> term::Result<()> {
self.map_result(|w| w.cursor_up())
}
fn delete_line(&mut self) -> term::Result<()> {
self.map_result(|w| w.delete_line())
}
fn carriage_return(&mut self) -> term::Result<()> {
self.map_result(|w| w.carriage_return())
}
fn get_ref(&self) -> &Self::Output {
match *self {
ColoredTerminal::Colored(ref w) => w.get_ref(),
ColoredTerminal::NoColor(ref w) => w,
}
}
fn get_mut(&mut self) -> &mut Self::Output {
match *self {
ColoredTerminal::Colored(ref mut w) => w.get_mut(),
ColoredTerminal::NoColor(ref mut w) => w,
}
}
fn into_inner(self) -> Self::Output {
match self {
ColoredTerminal::Colored(w) => w.into_inner(),
ColoredTerminal::NoColor(w) => w,
}
}
}
impl<'a, T: Terminal + Send> term::Terminal for &'a mut ColoredTerminal<T> {
type Output = T::Output;
fn fg(&mut self, fg: term::color::Color) -> term::Result<()> {
(**self).fg(fg)
}
fn bg(&mut self, bg: term::color::Color) -> term::Result<()> {
(**self).bg(bg)
}
fn attr(&mut self, attr: term::Attr) -> term::Result<()> {
(**self).attr(attr)
}
fn supports_attr(&self, attr: term::Attr) -> bool {
(**self).supports_attr(attr)
}
fn reset(&mut self) -> term::Result<()> {
(**self).reset()
}
fn supports_reset(&self) -> bool {
(**self).supports_reset()
}
fn supports_color(&self) -> bool {
(**self).supports_color()
}
fn cursor_up(&mut self) -> term::Result<()> {
(**self).cursor_up()
}
fn delete_line(&mut self) -> term::Result<()> {
(**self).delete_line()
}
fn carriage_return(&mut self) -> term::Result<()> {
(**self).carriage_return()
}
fn get_ref(&self) -> &Self::Output {
(**self).get_ref()
}
fn get_mut(&mut self) -> &mut Self::Output {
(**self).get_mut()
}
fn into_inner(self) -> Self::Output {
// Good golly miss molly...
unimplemented!()
}
}

118
src/pathutil.rs Normal file
View File

@@ -0,0 +1,118 @@
/*!
The pathutil module provides platform specific operations on paths that are
typically faster than the same operations as provided in std::path. In
particular, we really want to avoid the costly operation of parsing the path
into its constituent components. We give up on Windows, but on Unix, we deal
with the raw bytes directly.
On large repositories (like chromium), this can have a ~25% performance
improvement on just listing the files to search (!).
*/
use std::ffi::OsStr;
use std::path::Path;
/// Strip `prefix` from the `path` and return the remainder.
///
/// If `path` doesn't have a prefix `prefix`, then return `None`.
#[cfg(unix)]
pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
prefix: &'a P,
path: &'a Path,
) -> Option<&'a Path> {
use std::os::unix::ffi::OsStrExt;
let prefix = prefix.as_ref().as_os_str().as_bytes();
let path = path.as_os_str().as_bytes();
if prefix.len() > path.len() || prefix != &path[0..prefix.len()] {
None
} else {
Some(&Path::new(OsStr::from_bytes(&path[prefix.len()..])))
}
}
/// Strip `prefix` from the `path` and return the remainder.
///
/// If `path` doesn't have a prefix `prefix`, then return `None`.
#[cfg(not(unix))]
pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
prefix: &'a P,
path: &'a Path,
) -> Option<&'a Path> {
path.strip_prefix(prefix).ok()
}
/// The final component of the path, if it is a normal file.
///
/// If the path terminates in ., .., or consists solely of a root of prefix,
/// file_name will return None.
#[cfg(unix)]
pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
path: &'a P,
) -> Option<&'a OsStr> {
use std::os::unix::ffi::OsStrExt;
use memchr::memrchr;
let path = path.as_ref().as_os_str().as_bytes();
if path.is_empty() {
return None;
} else if path.len() == 1 && path[0] == b'.' {
return None;
} else if path.last() == Some(&b'.') {
return None;
} else if path.len() >= 2 && &path[path.len() - 2..] == &b".."[..] {
return None;
}
let last_slash = memrchr(b'/', path).map(|i| i + 1).unwrap_or(0);
Some(OsStr::from_bytes(&path[last_slash..]))
}
/// The final component of the path, if it is a normal file.
///
/// If the path terminates in ., .., or consists solely of a root of prefix,
/// file_name will return None.
#[cfg(not(unix))]
pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
path: &'a P,
) -> Option<&'a OsStr> {
path.as_ref().file_name()
}
/// Returns true if and only if this file path is considered to be hidden.
#[cfg(unix)]
pub fn is_hidden<P: AsRef<Path>>(path: P) -> bool {
use std::os::unix::ffi::OsStrExt;
if let Some(name) = file_name(path.as_ref()) {
name.as_bytes().get(0) == Some(&b'.')
} else {
false
}
}
/// Returns true if and only if this file path is considered to be hidden.
#[cfg(not(unix))]
pub fn is_hidden<P: AsRef<Path>>(path: P) -> bool {
if let Some(name) = file_name(path.as_ref()) {
name.to_str().map(|s| s.starts_with(".")).unwrap_or(false)
} else {
false
}
}
/// Returns true if this file path is just a file name. i.e., Its parent is
/// the empty string.
#[cfg(unix)]
pub fn is_file_name<P: AsRef<Path>>(path: P) -> bool {
use std::os::unix::ffi::OsStrExt;
use memchr::memchr;
let path = path.as_ref().as_os_str().as_bytes();
memchr(b'/', path).is_none()
}
/// Returns true if this file path is just a file name. i.e., Its parent is
/// the empty string.
#[cfg(not(unix))]
pub fn is_file_name<P: AsRef<Path>>(path: P) -> bool {
path.as_ref().parent().map(|p| p.as_os_str().is_empty()).unwrap_or(false)
}

View File

@@ -1,17 +1,12 @@
use std::io::{self, Write};
use std::path::Path;
use std::sync::Arc;
use regex::bytes::Regex;
use term::{self, Terminal};
use term::color::*;
use term::terminfo::TermInfo;
use term::{Attr, Terminal};
use term::color;
use terminal::TerminfoTerminal;
use pathutil::strip_prefix;
use types::FileTypeDef;
use self::Writer::*;
/// Printer encapsulates all output logic for searching.
///
/// Note that we currently ignore all write errors. It's probably worthwhile
@@ -19,44 +14,88 @@ use self::Writer::*;
/// writes to memory, neither of which commonly fail.
pub struct Printer<W> {
/// The underlying writer.
wtr: Writer<W>,
wtr: W,
/// Whether anything has been printed to wtr yet.
has_printed: bool,
/// Whether to show column numbers for the first match or not.
column: bool,
/// The string to use to separate non-contiguous runs of context lines.
context_separator: Vec<u8>,
/// The end-of-line terminator used by the printer. In general, eols are
/// printed via the match directly, but occasionally we need to insert them
/// ourselves (for example, to print a context separator).
eol: u8,
/// A file separator to show before any matches are printed.
file_separator: Option<Vec<u8>>,
/// Whether to show file name as a heading or not.
///
/// N.B. If with_filename is false, then this setting has no effect.
heading: bool,
/// Whether to suppress all output.
quiet: bool,
/// Whether to show every match on its own line.
line_per_match: bool,
/// Whether to print NUL bytes after a file path instead of new lines
/// or `:`.
null: bool,
/// A string to use as a replacement of each match in a matching line.
replace: Option<Vec<u8>>,
/// Whether to prefix each match with the corresponding file name.
with_filename: bool,
/// The choice of colors.
color_choice: ColorChoice
}
impl<W: Send + io::Write> Printer<W> {
struct ColorChoice {
matched_line: color::Color,
heading: color::Color,
line_number: color::Color
}
impl ColorChoice {
#[cfg(unix)]
pub fn new() -> ColorChoice {
ColorChoice {
matched_line: color::RED,
heading: color::GREEN,
line_number: color::BLUE
}
}
#[cfg(not(unix))]
pub fn new() -> ColorChoice {
ColorChoice {
matched_line: color::BRIGHT_RED,
heading: color::BRIGHT_GREEN,
line_number: color::BRIGHT_BLUE
}
}
}
impl<W: Terminal + Send> Printer<W> {
/// Create a new printer that writes to wtr.
///
/// `color` should be true if the printer should try to use coloring.
pub fn new(wtr: W, color: bool) -> Printer<W> {
pub fn new(wtr: W) -> Printer<W> {
Printer {
wtr: Writer::new(wtr, color),
wtr: wtr,
has_printed: false,
column: false,
context_separator: "--".to_string().into_bytes(),
eol: b'\n',
file_separator: None,
heading: false,
quiet: false,
line_per_match: false,
null: false,
replace: None,
with_filename: false,
color_choice: ColorChoice::new()
}
}
/// When set, column numbers will be printed for the first match on each
/// line.
pub fn column(mut self, yes: bool) -> Printer<W> {
self.column = yes;
self
}
/// Set the context separator. The default is `--`.
pub fn context_separator(mut self, sep: Vec<u8>) -> Printer<W> {
self.context_separator = sep;
@@ -69,6 +108,13 @@ impl<W: Send + io::Write> Printer<W> {
self
}
/// If set, the separator is printed before any matches. By default, no
/// separator is printed.
pub fn file_separator(mut self, sep: Vec<u8>) -> Printer<W> {
self.file_separator = Some(sep);
self
}
/// Whether to show file name as a heading or not.
///
/// N.B. If with_filename is false, then this setting has no effect.
@@ -77,9 +123,16 @@ impl<W: Send + io::Write> Printer<W> {
self
}
/// When set, all output is suppressed.
pub fn quiet(mut self, yes: bool) -> Printer<W> {
self.quiet = yes;
/// Whether to show every match on its own line.
pub fn line_per_match(mut self, yes: bool) -> Printer<W> {
self.line_per_match = yes;
self
}
/// Whether to cause NUL bytes to follow file paths instead of other
/// visual separators (like `:`, `-` and `\n`).
pub fn null(mut self, yes: bool) -> Printer<W> {
self.null = yes;
self
}
@@ -107,7 +160,7 @@ impl<W: Send + io::Write> Printer<W> {
/// Flushes the underlying writer and returns it.
pub fn into_inner(mut self) -> W {
let _ = self.wtr.flush();
self.wtr.into_inner()
self.wtr
}
/// Prints a type definition.
@@ -127,15 +180,24 @@ impl<W: Send + io::Write> Printer<W> {
/// Prints the given path.
pub fn path<P: AsRef<Path>>(&mut self, path: P) {
self.write(path.as_ref().to_string_lossy().as_bytes());
self.write_eol();
let path = strip_prefix("./", path.as_ref()).unwrap_or(path.as_ref());
self.write_path(path);
if self.null {
self.write(b"\x00");
} else {
self.write_eol();
}
}
/// Prints the given path and a count of the number of matches found.
pub fn path_count<P: AsRef<Path>>(&mut self, path: P, count: u64) {
if self.with_filename {
self.write(path.as_ref().to_string_lossy().as_bytes());
self.write(b":");
self.write_path(path);
if self.null {
self.write(b"\x00");
} else {
self.write(b":");
}
}
self.write(count.to_string().as_bytes());
self.write_eol();
@@ -144,9 +206,6 @@ impl<W: Send + io::Write> Printer<W> {
/// Prints the context separator.
pub fn context_separate(&mut self) {
// N.B. We can't use `write` here because of borrowing restrictions.
if self.quiet {
return;
}
if self.context_separator.is_empty() {
return;
}
@@ -163,38 +222,70 @@ impl<W: Send + io::Write> Printer<W> {
start: usize,
end: usize,
line_number: Option<u64>,
) {
if !self.line_per_match {
let column =
if self.column {
Some(re.find(&buf[start..end])
.map(|(s, _)| s).unwrap_or(0) as u64)
} else {
None
};
return self.write_match(
re, path, buf, start, end, line_number, column);
}
for (s, _) in re.find_iter(&buf[start..end]) {
let column = if self.column { Some(s as u64) } else { None };
self.write_match(
re, path.as_ref(), buf, start, end, line_number, column);
}
}
fn write_match<P: AsRef<Path>>(
&mut self,
re: &Regex,
path: P,
buf: &[u8],
start: usize,
end: usize,
line_number: Option<u64>,
column: Option<u64>,
) {
if self.heading && self.with_filename && !self.has_printed {
self.write_file_sep();
self.write_heading(path.as_ref());
} else if !self.heading && self.with_filename {
self.write(path.as_ref().to_string_lossy().as_bytes());
self.write(b":");
self.write_non_heading_path(path.as_ref());
}
if let Some(line_number) = line_number {
self.line_number(line_number, b':');
}
if let Some(c) = column {
self.write((c + 1).to_string().as_bytes());
self.write(b":");
}
if self.replace.is_some() {
let line = re.replace_all(
&buf[start..end], &**self.replace.as_ref().unwrap());
self.write(&line);
} else {
self.write_match(re, &buf[start..end]);
self.write_matched_line(re, &buf[start..end]);
}
if buf[start..end].last() != Some(&self.eol) {
self.write_eol();
}
}
pub fn write_match(&mut self, re: &Regex, buf: &[u8]) {
if !self.wtr.is_color() {
fn write_matched_line(&mut self, re: &Regex, buf: &[u8]) {
if !self.wtr.supports_color() {
self.write(buf);
return;
}
let mut last_written = 0;
for (s, e) in re.find_iter(buf) {
self.write(&buf[last_written..s]);
let _ = self.wtr.fg(BRIGHT_RED);
let _ = self.wtr.attr(term::Attr::Bold);
let _ = self.wtr.fg(self.color_choice.matched_line);
let _ = self.wtr.attr(Attr::Bold);
self.write(&buf[s..e]);
let _ = self.wtr.reset();
last_written = e;
@@ -211,10 +302,15 @@ impl<W: Send + io::Write> Printer<W> {
line_number: Option<u64>,
) {
if self.heading && self.with_filename && !self.has_printed {
self.write_file_sep();
self.write_heading(path.as_ref());
} else if !self.heading && self.with_filename {
self.write(path.as_ref().to_string_lossy().as_bytes());
self.write(b"-");
self.write_path(path.as_ref());
if self.null {
self.write(b"\x00");
} else {
self.write(b"-");
}
}
if let Some(line_number) = line_number {
self.line_number(line_number, b'-');
@@ -226,32 +322,63 @@ impl<W: Send + io::Write> Printer<W> {
}
fn write_heading<P: AsRef<Path>>(&mut self, path: P) {
if self.wtr.is_color() {
let _ = self.wtr.fg(GREEN);
if self.wtr.supports_color() {
let _ = self.wtr.fg(self.color_choice.heading);
let _ = self.wtr.attr(Attr::Bold);
}
self.write(path.as_ref().to_string_lossy().as_bytes());
self.write_eol();
if self.wtr.is_color() {
self.write_path(path.as_ref());
if self.null {
self.write(b"\x00");
} else {
self.write_eol();
}
if self.wtr.supports_color() {
let _ = self.wtr.reset();
}
}
fn write_non_heading_path<P: AsRef<Path>>(&mut self, path: P) {
if self.wtr.supports_color() {
let _ = self.wtr.fg(self.color_choice.heading);
let _ = self.wtr.attr(Attr::Bold);
}
self.write_path(path.as_ref());
if self.wtr.supports_color() {
let _ = self.wtr.reset();
}
if self.null {
self.write(b"\x00");
} else {
self.write(b":");
}
}
fn line_number(&mut self, n: u64, sep: u8) {
if self.wtr.is_color() {
let _ = self.wtr.fg(YELLOW);
let _ = self.wtr.attr(term::Attr::Bold);
if self.wtr.supports_color() {
let _ = self.wtr.fg(self.color_choice.line_number);
let _ = self.wtr.attr(Attr::Bold);
}
self.write(n.to_string().as_bytes());
if self.wtr.is_color() {
if self.wtr.supports_color() {
let _ = self.wtr.reset();
}
self.write(&[sep]);
}
#[cfg(unix)]
fn write_path<P: AsRef<Path>>(&mut self, path: P) {
use std::os::unix::ffi::OsStrExt;
let path = path.as_ref().as_os_str().as_bytes();
self.write(path);
}
#[cfg(not(unix))]
fn write_path<P: AsRef<Path>>(&mut self, path: P) {
self.write(path.as_ref().to_string_lossy().as_bytes());
}
fn write(&mut self, buf: &[u8]) {
if self.quiet {
return;
}
self.has_printed = true;
let _ = self.wtr.write_all(buf);
}
@@ -260,149 +387,12 @@ impl<W: Send + io::Write> Printer<W> {
let eol = self.eol;
self.write(&[eol]);
}
}
enum Writer<W> {
Colored(TerminfoTerminal<W>),
NoColor(W),
}
lazy_static! {
static ref TERMINFO: Option<Arc<TermInfo>> = {
match term::terminfo::TermInfo::from_env() {
Ok(info) => Some(Arc::new(info)),
Err(err) => {
debug!("error loading terminfo for coloring: {}", err);
None
}
}
};
}
impl<W: Send + io::Write> Writer<W> {
fn new(wtr: W, color: bool) -> Writer<W> {
// If we want color, build a TerminfoTerminal and see if the current
// environment supports coloring. If not, bail with NoColor. To avoid
// losing our writer (ownership), do this the long way.
if !color || TERMINFO.is_none() {
return NoColor(wtr);
}
let info = TERMINFO.clone().unwrap();
let tt = TerminfoTerminal::new_with_terminfo(wtr, info);
if !tt.supports_color() {
debug!("environment doesn't support coloring");
return NoColor(tt.into_inner());
}
Colored(tt)
}
fn is_color(&self) -> bool {
match *self {
Colored(_) => true,
NoColor(_) => false,
}
}
fn map_result<F>(
&mut self,
mut f: F,
) -> term::Result<()>
where F: FnMut(&mut TerminfoTerminal<W>) -> term::Result<()> {
match *self {
Colored(ref mut w) => f(w),
NoColor(_) => Err(term::Error::NotSupported),
}
}
fn map_bool<F>(
&self,
mut f: F,
) -> bool
where F: FnMut(&TerminfoTerminal<W>) -> bool {
match *self {
Colored(ref w) => f(w),
NoColor(_) => false,
}
}
}
impl<W: Send + io::Write> io::Write for Writer<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match *self {
Colored(ref mut w) => w.write(buf),
NoColor(ref mut w) => w.write(buf),
}
}
fn flush(&mut self) -> io::Result<()> {
match *self {
Colored(ref mut w) => w.flush(),
NoColor(ref mut w) => w.flush(),
}
}
}
impl<W: Send + io::Write> term::Terminal for Writer<W> {
type Output = W;
fn fg(&mut self, fg: term::color::Color) -> term::Result<()> {
self.map_result(|w| w.fg(fg))
}
fn bg(&mut self, bg: term::color::Color) -> term::Result<()> {
self.map_result(|w| w.bg(bg))
}
fn attr(&mut self, attr: term::Attr) -> term::Result<()> {
self.map_result(|w| w.attr(attr))
}
fn supports_attr(&self, attr: term::Attr) -> bool {
self.map_bool(|w| w.supports_attr(attr))
}
fn reset(&mut self) -> term::Result<()> {
self.map_result(|w| w.reset())
}
fn supports_reset(&self) -> bool {
self.map_bool(|w| w.supports_reset())
}
fn supports_color(&self) -> bool {
self.map_bool(|w| w.supports_color())
}
fn cursor_up(&mut self) -> term::Result<()> {
self.map_result(|w| w.cursor_up())
}
fn delete_line(&mut self) -> term::Result<()> {
self.map_result(|w| w.delete_line())
}
fn carriage_return(&mut self) -> term::Result<()> {
self.map_result(|w| w.carriage_return())
}
fn get_ref(&self) -> &W {
match *self {
Colored(ref w) => w.get_ref(),
NoColor(ref w) => w,
}
}
fn get_mut(&mut self) -> &mut W {
match *self {
Colored(ref mut w) => w.get_mut(),
NoColor(ref mut w) => w,
}
}
fn into_inner(self) -> W {
match self {
Colored(w) => w.into_inner(),
NoColor(w) => w,
fn write_file_sep(&mut self) {
if let Some(ref sep) = self.file_separator {
self.has_printed = true;
let _ = self.wtr.write_all(sep);
let _ = self.wtr.write_all(b"\n");
}
}
}

304
src/search_buffer.rs Normal file
View File

@@ -0,0 +1,304 @@
/*!
The search_buffer module is responsible for searching a single file all in a
single buffer. Typically, the source of the buffer is a memory map. This can
be useful for when memory maps are faster than streaming search.
Note that this module doesn't quite support everything that search_stream does.
Notably, showing contexts.
*/
use std::cmp;
use std::path::Path;
use grep::Grep;
use term::Terminal;
use printer::Printer;
use search_stream::{IterLines, Options, count_lines, is_binary};
pub struct BufferSearcher<'a, W: 'a> {
opts: Options,
printer: &'a mut Printer<W>,
grep: &'a Grep,
path: &'a Path,
buf: &'a [u8],
match_count: u64,
line_count: Option<u64>,
last_line: usize,
}
impl<'a, W: Send + Terminal> BufferSearcher<'a, W> {
pub fn new(
printer: &'a mut Printer<W>,
grep: &'a Grep,
path: &'a Path,
buf: &'a [u8],
) -> BufferSearcher<'a, W> {
BufferSearcher {
opts: Options::default(),
printer: printer,
grep: grep,
path: path,
buf: buf,
match_count: 0,
line_count: None,
last_line: 0,
}
}
/// If enabled, searching will print a count instead of each match.
///
/// Disabled by default.
pub fn count(mut self, yes: bool) -> Self {
self.opts.count = yes;
self
}
/// If enabled, searching will print the path instead of each match.
///
/// Disabled by default.
pub fn files_with_matches(mut self, yes: bool) -> Self {
self.opts.files_with_matches = yes;
self
}
/// Set the end-of-line byte used by this searcher.
pub fn eol(mut self, eol: u8) -> Self {
self.opts.eol = eol;
self
}
/// If enabled, matching is inverted so that lines that *don't* match the
/// given pattern are treated as matches.
pub fn invert_match(mut self, yes: bool) -> Self {
self.opts.invert_match = yes;
self
}
/// If enabled, compute line numbers and prefix each line of output with
/// them.
pub fn line_number(mut self, yes: bool) -> Self {
self.opts.line_number = yes;
self
}
/// If enabled, don't show any output and quit searching after the first
/// match is found.
pub fn quiet(mut self, yes: bool) -> Self {
self.opts.quiet = yes;
self
}
/// If enabled, search binary files as if they were text.
pub fn text(mut self, yes: bool) -> Self {
self.opts.text = yes;
self
}
#[inline(never)]
pub fn run(mut self) -> u64 {
let binary_upto = cmp::min(4096, self.buf.len());
if !self.opts.text && is_binary(&self.buf[..binary_upto]) {
return 0;
}
self.match_count = 0;
self.line_count = if self.opts.line_number { Some(0) } else { None };
let mut last_end = 0;
for m in self.grep.iter(self.buf) {
if self.opts.invert_match {
self.print_inverted_matches(last_end, m.start());
} else {
self.print_match(m.start(), m.end());
}
last_end = m.end();
if self.opts.stop_after_first_match() {
break;
}
}
if self.opts.invert_match {
let upto = self.buf.len();
self.print_inverted_matches(last_end, upto);
}
if self.opts.count && self.match_count > 0 {
self.printer.path_count(self.path, self.match_count);
}
if self.opts.files_with_matches && self.match_count > 0 {
self.printer.path(self.path);
}
self.match_count
}
#[inline(always)]
pub fn print_match(&mut self, start: usize, end: usize) {
self.match_count += 1;
if self.opts.skip_matches() {
return;
}
self.count_lines(start);
self.add_line(end);
self.printer.matched(
self.grep.regex(), self.path, self.buf,
start, end, self.line_count);
}
#[inline(always)]
fn print_inverted_matches(&mut self, start: usize, end: usize) {
debug_assert!(self.opts.invert_match);
let mut it = IterLines::new(self.opts.eol, start);
while let Some((s, e)) = it.next(&self.buf[..end]) {
self.print_match(s, e);
}
}
#[inline(always)]
fn count_lines(&mut self, upto: usize) {
if let Some(ref mut line_count) = self.line_count {
*line_count += count_lines(
&self.buf[self.last_line..upto], self.opts.eol);
self.last_line = upto;
}
}
#[inline(always)]
fn add_line(&mut self, line_end: usize) {
if let Some(ref mut line_count) = self.line_count {
*line_count += 1;
self.last_line = line_end;
}
}
}
#[cfg(test)]
mod tests {
use std::path::Path;
use grep::GrepBuilder;
use term::{Terminal, TerminfoTerminal};
use out::ColoredTerminal;
use printer::Printer;
use super::BufferSearcher;
const SHERLOCK: &'static str = "\
For the Doctor Watsons of this world, as opposed to the Sherlock
Holmeses, success in the province of detective work must always
be, to a very large extent, the result of luck. Sherlock Holmes
can extract a clew from a wisp of straw or a flake of cigar ash;
but Doctor Watson has to have it taken out for him and dusted,
and exhibited clearly, with a label attached.\
";
fn test_path() -> &'static Path {
&Path::new("/baz.rs")
}
type TestSearcher<'a> =
BufferSearcher<'a, ColoredTerminal<TerminfoTerminal<Vec<u8>>>>;
fn search<F: FnMut(TestSearcher) -> TestSearcher>(
pat: &str,
haystack: &str,
mut map: F,
) -> (u64, String) {
let outbuf = ColoredTerminal::NoColor(vec![]);
let mut pp = Printer::new(outbuf).with_filename(true);
let grep = GrepBuilder::new(pat).build().unwrap();
let count = {
let searcher = BufferSearcher::new(
&mut pp, &grep, test_path(), haystack.as_bytes());
map(searcher).run()
};
(count, String::from_utf8(pp.into_inner().into_inner()).unwrap())
}
#[test]
fn basic_search() {
let (count, out) = search("Sherlock", SHERLOCK, |s|s);
assert_eq!(2, count);
assert_eq!(out, "\
/baz.rs:For the Doctor Watsons of this world, as opposed to the Sherlock
/baz.rs:be, to a very large extent, the result of luck. Sherlock Holmes
");
}
#[test]
fn binary() {
let text = "Sherlock\n\x00Holmes\n";
let (count, out) = search("Sherlock|Holmes", text, |s|s);
assert_eq!(0, count);
assert_eq!(out, "");
}
#[test]
fn binary_text() {
let text = "Sherlock\n\x00Holmes\n";
let (count, out) = search("Sherlock|Holmes", text, |s| s.text(true));
assert_eq!(2, count);
assert_eq!(out, "/baz.rs:Sherlock\n/baz.rs:\x00Holmes\n");
}
#[test]
fn line_numbers() {
let (count, out) = search(
"Sherlock", SHERLOCK, |s| s.line_number(true));
assert_eq!(2, count);
assert_eq!(out, "\
/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
/baz.rs:3:be, to a very large extent, the result of luck. Sherlock Holmes
");
}
#[test]
fn count() {
let (count, out) = search(
"Sherlock", SHERLOCK, |s| s.count(true));
assert_eq!(2, count);
assert_eq!(out, "/baz.rs:2\n");
}
#[test]
fn files_with_matches() {
let (count, out) = search(
"Sherlock", SHERLOCK, |s| s.files_with_matches(true));
assert_eq!(1, count);
assert_eq!(out, "/baz.rs\n");
}
#[test]
fn invert_match() {
let (count, out) = search(
"Sherlock", SHERLOCK, |s| s.invert_match(true));
assert_eq!(4, count);
assert_eq!(out, "\
/baz.rs:Holmeses, success in the province of detective work must always
/baz.rs:can extract a clew from a wisp of straw or a flake of cigar ash;
/baz.rs:but Doctor Watson has to have it taken out for him and dusted,
/baz.rs:and exhibited clearly, with a label attached.
");
}
#[test]
fn invert_match_line_numbers() {
let (count, out) = search("Sherlock", SHERLOCK, |s| {
s.invert_match(true).line_number(true)
});
assert_eq!(4, count);
assert_eq!(out, "\
/baz.rs:2:Holmeses, success in the province of detective work must always
/baz.rs:4:can extract a clew from a wisp of straw or a flake of cigar ash;
/baz.rs:5:but Doctor Watson has to have it taken out for him and dusted,
/baz.rs:6:and exhibited clearly, with a label attached.
");
}
#[test]
fn invert_match_count() {
let (count, out) = search("Sherlock", SHERLOCK, |s| {
s.invert_match(true).count(true)
});
assert_eq!(4, count);
assert_eq!(out, "/baz.rs:4\n");
}
}

View File

@@ -1,6 +1,7 @@
/*!
The search module is responsible for searching a single file and printing
matches.
The search_stream module is responsible for searching a single file and
printing matches. In particular, it searches the file in a streaming fashion
using `read` calls and a (roughly) fixed size buffer.
*/
use std::cmp;
@@ -11,6 +12,7 @@ use std::path::{Path, PathBuf};
use grep::{Grep, Match};
use memchr::{memchr, memrchr};
use term::Terminal;
use printer::Printer;
@@ -74,14 +76,16 @@ pub struct Searcher<'a, R, W: 'a> {
/// Options for configuring search.
#[derive(Clone)]
struct Options {
after_context: usize,
before_context: usize,
count: bool,
eol: u8,
invert_match: bool,
line_number: bool,
text: bool,
pub struct Options {
pub after_context: usize,
pub before_context: usize,
pub count: bool,
pub files_with_matches: bool,
pub eol: u8,
pub invert_match: bool,
pub line_number: bool,
pub quiet: bool,
pub text: bool,
}
impl Default for Options {
@@ -90,15 +94,32 @@ impl Default for Options {
after_context: 0,
before_context: 0,
count: false,
files_with_matches: false,
eol: b'\n',
invert_match: false,
line_number: false,
quiet: false,
text: false,
}
}
}
impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
impl Options {
/// Several options (--quiet, --count, --files-with-matches) imply that
/// we shouldn't ever display matches.
pub fn skip_matches(&self) -> bool {
self.count || self.files_with_matches || self.quiet
}
/// Some options (--quiet, --files-with-matches) imply that we can stop
/// searching after the first match.
pub fn stop_after_first_match(&self) -> bool {
self.files_with_matches || self.quiet
}
}
impl<'a, R: io::Read, W: Terminal + Send> Searcher<'a, R, W> {
/// Create a new searcher.
///
/// `inp` is a reusable input buffer that is used as scratch space by this
@@ -156,6 +177,14 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
self
}
/// If enabled, searching will print the path instead of each match.
///
/// Disabled by default.
pub fn files_with_matches(mut self, yes: bool) -> Self {
self.opts.files_with_matches = yes;
self
}
/// Set the end-of-line byte used by this searcher.
pub fn eol(mut self, eol: u8) -> Self {
self.opts.eol = eol;
@@ -176,6 +205,13 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
self
}
/// If enabled, don't show any output and quit searching after the first
/// match is found.
pub fn quiet(mut self, yes: bool) -> Self {
self.opts.quiet = yes;
self
}
/// If enabled, search binary files as if they were text.
pub fn text(mut self, yes: bool) -> Self {
self.opts.text = yes;
@@ -191,7 +227,7 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
self.line_count = if self.opts.line_number { Some(0) } else { None };
self.last_match = Match::default();
self.after_context_remaining = 0;
loop {
while !self.terminate() {
let upto = self.inp.lastnl;
self.print_after_context(upto);
if !try!(self.fill()) {
@@ -200,7 +236,7 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
if !self.opts.text && self.inp.is_binary {
break;
}
while self.inp.pos < self.inp.lastnl {
while !self.terminate() && self.inp.pos < self.inp.lastnl {
let matched = self.grep.read_match(
&mut self.last_match,
&mut self.inp.buf[..self.inp.lastnl],
@@ -219,14 +255,11 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
self.print_inverted_matches(upto);
}
} else if matched {
self.match_count += 1;
if !self.opts.count {
let start = self.last_match.start();
let end = self.last_match.end();
self.print_after_context(start);
self.print_before_context(start);
self.print_match(start, end);
}
let start = self.last_match.start();
let end = self.last_match.end();
self.print_after_context(start);
self.print_before_context(start);
self.print_match(start, end);
}
if matched {
self.inp.pos = self.last_match.end();
@@ -235,12 +268,21 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
}
}
}
if self.opts.count && self.match_count > 0 {
self.printer.path_count(self.path, self.match_count);
if self.match_count > 0 {
if self.opts.count {
self.printer.path_count(self.path, self.match_count);
} else if self.opts.files_with_matches {
self.printer.path(self.path);
}
}
Ok(self.match_count)
}
#[inline(always)]
fn terminate(&self) -> bool {
self.match_count > 0 && self.opts.stop_after_first_match()
}
#[inline(always)]
fn fill(&mut self) -> Result<bool, Error> {
let mut keep = self.inp.lastnl;
@@ -275,17 +317,14 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
debug_assert!(self.opts.invert_match);
let mut it = IterLines::new(self.opts.eol, self.inp.pos);
while let Some((start, end)) = it.next(&self.inp.buf[..upto]) {
if !self.opts.count {
self.print_match(start, end);
}
self.print_match(start, end);
self.inp.pos = end;
self.match_count += 1;
}
}
#[inline(always)]
fn print_before_context(&mut self, upto: usize) {
if self.opts.count || self.opts.before_context == 0 {
if self.opts.skip_matches() || self.opts.before_context == 0 {
return;
}
let start = self.last_printed;
@@ -308,7 +347,7 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
#[inline(always)]
fn print_after_context(&mut self, upto: usize) {
if self.opts.count || self.after_context_remaining == 0 {
if self.opts.skip_matches() || self.after_context_remaining == 0 {
return;
}
let start = self.last_printed;
@@ -325,11 +364,15 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
#[inline(always)]
fn print_match(&mut self, start: usize, end: usize) {
self.match_count += 1;
if self.opts.skip_matches() {
return;
}
self.print_separator(start);
self.count_lines(start);
self.add_line(end);
self.printer.matched(
self.grep.regex(), &self.path,
self.grep.regex(), self.path,
&self.inp.buf, start, end, self.line_count);
self.last_printed = end;
self.after_context_remaining = self.opts.after_context;
@@ -503,10 +546,6 @@ impl InputBuffer {
if self.first && is_binary(&self.buf[self.end..self.end + n]) {
self.is_binary = true;
}
if self.is_binary {
replace_buf(
&mut self.buf[self.end..self.end + n], b'\x00', self.eol);
}
self.first = false;
// We assume that reading 0 bytes means we've hit EOF.
if n == 0 {
@@ -535,7 +574,7 @@ impl InputBuffer {
///
/// Note that this may return both false positives and false negatives.
#[inline(always)]
fn is_binary(buf: &[u8]) -> bool {
pub fn is_binary(buf: &[u8]) -> bool {
if buf.len() >= 4 && &buf[0..4] == b"%PDF" {
return true;
}
@@ -543,17 +582,93 @@ fn is_binary(buf: &[u8]) -> bool {
}
/// Count the number of lines in the given buffer.
#[inline(always)]
fn count_lines(mut buf: &[u8], eol: u8) -> u64 {
let mut count = 0;
while let Some(pos) = memchr(eol, buf) {
count += 1;
buf = &buf[pos + 1..];
#[inline(never)]
#[inline(never)]
pub fn count_lines(buf: &[u8], eol: u8) -> u64 {
// This was adapted from code in the memchr crate. The specific benefit
// here is that we can avoid a branch in the inner loop because all we're
// doing is counting.
// The technique to count EOL bytes was adapted from:
// http://bits.stephan-brumme.com/null.html
const LO_U64: u64 = 0x0101010101010101;
const HI_U64: u64 = 0x8080808080808080;
// use truncation
const LO_USIZE: usize = LO_U64 as usize;
const HI_USIZE: usize = HI_U64 as usize;
#[cfg(target_pointer_width = "32")]
const USIZE_BYTES: usize = 4;
#[cfg(target_pointer_width = "64")]
const USIZE_BYTES: usize = 8;
fn count_eol(eol: usize) -> u64 {
// Ideally, this would compile down to a POPCNT instruction, but
// it looks like you need to set RUSTFLAGS="-C target-cpu=native"
// (or target-feature=+popcnt) to get that to work. Bummer.
(eol.wrapping_sub(LO_USIZE) & !eol & HI_USIZE).count_ones() as u64
}
#[cfg(target_pointer_width = "32")]
fn repeat_byte(b: u8) -> usize {
let mut rep = (b as usize) << 8 | b as usize;
rep = rep << 16 | rep;
rep
}
#[cfg(target_pointer_width = "64")]
fn repeat_byte(b: u8) -> usize {
let mut rep = (b as usize) << 8 | b as usize;
rep = rep << 16 | rep;
rep = rep << 32 | rep;
rep
}
fn count_lines_slow(mut buf: &[u8], eol: u8) -> u64 {
let mut count = 0;
while let Some(pos) = memchr(eol, buf) {
count += 1;
buf = &buf[pos + 1..];
}
count
}
let len = buf.len();
let ptr = buf.as_ptr();
let mut count = 0;
// Search up to an aligned boundary...
let align = (ptr as usize) & (USIZE_BYTES - 1);
let mut i = 0;
if align > 0 {
i = cmp::min(USIZE_BYTES - align, len);
count += count_lines_slow(&buf[..i], eol);
}
// ... and search the rest.
let repeated_eol = repeat_byte(eol);
if len >= 2 * USIZE_BYTES {
while i <= len - (2 * USIZE_BYTES) {
unsafe {
let u = *(ptr.offset(i as isize) as *const usize);
let v = *(ptr.offset((i + USIZE_BYTES) as isize)
as *const usize);
count += count_eol(u ^ repeated_eol);
count += count_eol(v ^ repeated_eol);
}
i += USIZE_BYTES * 2;
}
}
count += count_lines_slow(&buf[i..], eol);
count
}
/// Replaces a with b in buf.
#[allow(dead_code)]
fn replace_buf(buf: &mut [u8], a: u8, b: u8) {
if a == b {
return;
@@ -575,7 +690,7 @@ fn replace_buf(buf: &mut [u8], a: u8, b: u8) {
/// advance over the positions of each line. We neglect that approach to avoid
/// the borrow in the search code. (Because the borrow prevents composition
/// through other mutable methods.)
struct IterLines {
pub struct IterLines {
eol: u8,
pos: usize,
}
@@ -585,7 +700,7 @@ impl IterLines {
///
/// The buffer is passed to the `next` method.
#[inline(always)]
fn new(eol: u8, start: usize) -> IterLines {
pub fn new(eol: u8, start: usize) -> IterLines {
IterLines {
eol: eol,
pos: start,
@@ -597,7 +712,7 @@ impl IterLines {
///
/// The range returned includes the new line.
#[inline(always)]
fn next(&mut self, buf: &[u8]) -> Option<(usize, usize)> {
pub fn next(&mut self, buf: &[u8]) -> Option<(usize, usize)> {
match memchr(self.eol, &buf[self.pos..]) {
None => {
if self.pos < buf.len() {
@@ -688,14 +803,15 @@ mod tests {
use std::io;
use std::path::Path;
use grep::{Grep, GrepBuilder};
use grep::GrepBuilder;
use term::{Terminal, TerminfoTerminal};
use out::ColoredTerminal;
use printer::Printer;
use super::{InputBuffer, Searcher, start_of_previous_lines};
lazy_static! {
static ref SHERLOCK: &'static str = "\
const SHERLOCK: &'static str = "\
For the Doctor Watsons of this world, as opposed to the Sherlock
Holmeses, success in the province of detective work must always
be, to a very large extent, the result of luck. Sherlock Holmes
@@ -703,7 +819,8 @@ can extract a clew from a wisp of straw or a flake of cigar ash;
but Doctor Watson has to have it taken out for him and dusted,
and exhibited clearly, with a label attached.\
";
static ref CODE: &'static str = "\
const CODE: &'static str = "\
extern crate snap;
use std::io;
@@ -718,21 +835,20 @@ fn main() {
io::copy(&mut rdr, &mut wtr).expect(\"I/O operation failed\");
}
";
}
fn hay(s: &str) -> io::Cursor<Vec<u8>> {
io::Cursor::new(s.to_string().into_bytes())
}
fn matcher(pat: &str) -> Grep {
GrepBuilder::new(pat).build().unwrap()
}
fn test_path() -> &'static Path {
&Path::new("/baz.rs")
}
type TestSearcher<'a> = Searcher<'a, io::Cursor<Vec<u8>>, Vec<u8>>;
type TestSearcher<'a> = Searcher<
'a,
io::Cursor<Vec<u8>>,
ColoredTerminal<TerminfoTerminal<Vec<u8>>>,
>;
fn search_smallcap<F: FnMut(TestSearcher) -> TestSearcher>(
pat: &str,
@@ -740,14 +856,15 @@ fn main() {
mut map: F,
) -> (u64, String) {
let mut inp = InputBuffer::with_capacity(1);
let mut pp = Printer::new(vec![], false).with_filename(true);
let outbuf = ColoredTerminal::NoColor(vec![]);
let mut pp = Printer::new(outbuf).with_filename(true);
let grep = GrepBuilder::new(pat).build().unwrap();
let count = {
let searcher = Searcher::new(
&mut inp, &mut pp, &grep, test_path(), hay(haystack));
map(searcher).run().unwrap()
};
(count, String::from_utf8(pp.into_inner()).unwrap())
(count, String::from_utf8(pp.into_inner().into_inner()).unwrap())
}
fn search<F: FnMut(TestSearcher) -> TestSearcher>(
@@ -756,14 +873,15 @@ fn main() {
mut map: F,
) -> (u64, String) {
let mut inp = InputBuffer::with_capacity(4096);
let mut pp = Printer::new(vec![], false).with_filename(true);
let outbuf = ColoredTerminal::NoColor(vec![]);
let mut pp = Printer::new(outbuf).with_filename(true);
let grep = GrepBuilder::new(pat).build().unwrap();
let count = {
let searcher = Searcher::new(
&mut inp, &mut pp, &grep, test_path(), hay(haystack));
map(searcher).run().unwrap()
};
(count, String::from_utf8(pp.into_inner()).unwrap())
(count, String::from_utf8(pp.into_inner().into_inner()).unwrap())
}
#[test]
@@ -870,8 +988,8 @@ fn main() {
}
#[test]
fn basic_search() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s|s);
fn basic_search1() {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s|s);
assert_eq!(2, count);
assert_eq!(out, "\
/baz.rs:For the Doctor Watsons of this world, as opposed to the Sherlock
@@ -887,19 +1005,18 @@ fn main() {
assert_eq!(out, "");
}
#[test]
fn binary_text() {
let text = "Sherlock\n\x00Holmes\n";
let (count, out) = search("Sherlock|Holmes", text, |s| s.text(true));
assert_eq!(2, count);
assert_eq!(out, "/baz.rs:Sherlock\n/baz.rs:Holmes\n");
assert_eq!(out, "/baz.rs:Sherlock\n/baz.rs:\x00Holmes\n");
}
#[test]
fn line_numbers() {
let (count, out) = search_smallcap(
"Sherlock", &*SHERLOCK, |s| s.line_number(true));
"Sherlock", SHERLOCK, |s| s.line_number(true));
assert_eq!(2, count);
assert_eq!(out, "\
/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
@@ -910,15 +1027,23 @@ fn main() {
#[test]
fn count() {
let (count, out) = search_smallcap(
"Sherlock", &*SHERLOCK, |s| s.count(true));
"Sherlock", SHERLOCK, |s| s.count(true));
assert_eq!(2, count);
assert_eq!(out, "/baz.rs:2\n");
}
#[test]
fn files_with_matches() {
let (count, out) = search_smallcap(
"Sherlock", SHERLOCK, |s| s.files_with_matches(true));
assert_eq!(1, count);
assert_eq!(out, "/baz.rs\n");
}
#[test]
fn invert_match() {
let (count, out) = search_smallcap(
"Sherlock", &*SHERLOCK, |s| s.invert_match(true));
"Sherlock", SHERLOCK, |s| s.invert_match(true));
assert_eq!(4, count);
assert_eq!(out, "\
/baz.rs:Holmeses, success in the province of detective work must always
@@ -930,7 +1055,7 @@ fn main() {
#[test]
fn invert_match_line_numbers() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.invert_match(true).line_number(true)
});
assert_eq!(4, count);
@@ -944,7 +1069,7 @@ fn main() {
#[test]
fn invert_match_count() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.invert_match(true).count(true)
});
assert_eq!(4, count);
@@ -953,7 +1078,7 @@ fn main() {
#[test]
fn before_context_one1() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.line_number(true).before_context(1)
});
assert_eq!(2, count);
@@ -966,7 +1091,7 @@ fn main() {
#[test]
fn before_context_invert_one1() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.line_number(true).before_context(1).invert_match(true)
});
assert_eq!(4, count);
@@ -982,7 +1107,7 @@ fn main() {
#[test]
fn before_context_invert_one2() {
let (count, out) = search_smallcap(" a ", &*SHERLOCK, |s| {
let (count, out) = search_smallcap(" a ", SHERLOCK, |s| {
s.line_number(true).before_context(1).invert_match(true)
});
assert_eq!(3, count);
@@ -997,7 +1122,7 @@ fn main() {
#[test]
fn before_context_two1() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.line_number(true).before_context(2)
});
assert_eq!(2, count);
@@ -1010,7 +1135,7 @@ fn main() {
#[test]
fn before_context_two2() {
let (count, out) = search_smallcap("dusted", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("dusted", SHERLOCK, |s| {
s.line_number(true).before_context(2)
});
assert_eq!(1, count);
@@ -1024,7 +1149,7 @@ fn main() {
#[test]
fn before_context_two3() {
let (count, out) = search_smallcap(
"success|attached", &*SHERLOCK, |s| {
"success|attached", SHERLOCK, |s| {
s.line_number(true).before_context(2)
});
assert_eq!(2, count);
@@ -1040,7 +1165,7 @@ fn main() {
#[test]
fn before_context_two4() {
let (count, out) = search("stdin", &*CODE, |s| {
let (count, out) = search("stdin", CODE, |s| {
s.line_number(true).before_context(2)
});
assert_eq!(3, count);
@@ -1057,7 +1182,7 @@ fn main() {
#[test]
fn before_context_two5() {
let (count, out) = search("stdout", &*CODE, |s| {
let (count, out) = search("stdout", CODE, |s| {
s.line_number(true).before_context(2)
});
assert_eq!(2, count);
@@ -1074,7 +1199,7 @@ fn main() {
#[test]
fn before_context_three1() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.line_number(true).before_context(3)
});
assert_eq!(2, count);
@@ -1087,7 +1212,7 @@ fn main() {
#[test]
fn after_context_one1() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.line_number(true).after_context(1)
});
assert_eq!(2, count);
@@ -1101,7 +1226,7 @@ fn main() {
#[test]
fn after_context_invert_one1() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.line_number(true).after_context(1).invert_match(true)
});
assert_eq!(4, count);
@@ -1116,7 +1241,7 @@ fn main() {
#[test]
fn after_context_invert_one2() {
let (count, out) = search_smallcap(" a ", &*SHERLOCK, |s| {
let (count, out) = search_smallcap(" a ", SHERLOCK, |s| {
s.line_number(true).after_context(1).invert_match(true)
});
assert_eq!(3, count);
@@ -1132,7 +1257,7 @@ fn main() {
#[test]
fn after_context_two1() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.line_number(true).after_context(2)
});
assert_eq!(2, count);
@@ -1147,7 +1272,7 @@ fn main() {
#[test]
fn after_context_two2() {
let (count, out) = search_smallcap("dusted", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("dusted", SHERLOCK, |s| {
s.line_number(true).after_context(2)
});
assert_eq!(1, count);
@@ -1160,7 +1285,7 @@ fn main() {
#[test]
fn after_context_two3() {
let (count, out) = search_smallcap(
"success|attached", &*SHERLOCK, |s| {
"success|attached", SHERLOCK, |s| {
s.line_number(true).after_context(2)
});
assert_eq!(2, count);
@@ -1175,7 +1300,7 @@ fn main() {
#[test]
fn after_context_three1() {
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
s.line_number(true).after_context(3)
});
assert_eq!(2, count);
@@ -1192,7 +1317,7 @@ fn main() {
#[test]
fn before_after_context_two1() {
let (count, out) = search(
r"fn main|let mut rdr", &*CODE, |s| {
r"fn main|let mut rdr", CODE, |s| {
s.line_number(true).after_context(2).before_context(2)
});
assert_eq!(2, count);

View File

@@ -1,42 +0,0 @@
/*!
This io module contains various platform specific functions for detecting
how xrep is being used. e.g., Is stdin being piped into it? Is stdout being
redirected to a file? etc... We use this information to tweak various default
configuration parameters such as colors and match formatting.
*/
use libc;
#[cfg(unix)]
pub fn stdin_is_atty() -> bool {
0 < unsafe { libc::isatty(libc::STDIN_FILENO) }
}
#[cfg(unix)]
pub fn stdout_is_atty() -> bool {
0 < unsafe { libc::isatty(libc::STDOUT_FILENO) }
}
#[cfg(windows)]
pub fn stdin_is_atty() -> bool {
use kernel32;
use winapi;
unsafe {
let fd = winapi::winbase::STD_INPUT_HANDLE;
let mut out = 0;
kernel32::GetConsoleMode(kernel32::GetStdHandle(fd), &mut out) != 0
}
}
#[cfg(windows)]
pub fn stdout_is_atty() -> bool {
use kernel32;
use winapi;
unsafe {
let fd = winapi::winbase::STD_OUTPUT_HANDLE;
let mut out = 0;
kernel32::GetConsoleMode(kernel32::GetStdHandle(fd), &mut out) != 0
}
}

View File

@@ -1,202 +0,0 @@
/*!
This module contains an implementation of the `term::Terminal` trait.
The actual implementation is copied almost verbatim from the `term` crate, so
this code is under the same license (MIT/Apache).
The specific reason why this is copied here is to wrap an Arc<TermInfo> instead
of a TermInfo. This makes multithreaded sharing much more performant.
N.B. This is temporary until this issue is fixed:
https://github.com/Stebalien/term/issues/64
*/
use std::io::{self, Write};
use std::sync::Arc;
use term::{Attr, Error, Result, Terminal, color};
use term::terminfo::TermInfo;
use term::terminfo::parm::{Param, Variables, expand};
/// A Terminal that knows how many colors it supports, with a reference to its
/// parsed Terminfo database record.
#[derive(Clone, Debug)]
pub struct TerminfoTerminal<T> {
num_colors: u16,
out: T,
ti: Arc<TermInfo>,
}
impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
type Output = T;
fn fg(&mut self, color: color::Color) -> Result<()> {
let color = self.dim_if_necessary(color);
if self.num_colors > color {
return apply_cap(&self.ti, "setaf", &[Param::Number(color as i32)], &mut self.out);
}
Err(Error::ColorOutOfRange)
}
fn bg(&mut self, color: color::Color) -> Result<()> {
let color = self.dim_if_necessary(color);
if self.num_colors > color {
return apply_cap(&self.ti, "setab", &[Param::Number(color as i32)], &mut self.out);
}
Err(Error::ColorOutOfRange)
}
fn attr(&mut self, attr: Attr) -> Result<()> {
match attr {
Attr::ForegroundColor(c) => self.fg(c),
Attr::BackgroundColor(c) => self.bg(c),
_ => apply_cap(&self.ti, cap_for_attr(attr), &[], &mut self.out),
}
}
fn supports_attr(&self, attr: Attr) -> bool {
match attr {
Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0,
_ => {
let cap = cap_for_attr(attr);
self.ti.strings.get(cap).is_some()
}
}
}
fn reset(&mut self) -> Result<()> {
reset(&self.ti, &mut self.out)
}
fn supports_reset(&self) -> bool {
["sgr0", "sgr", "op"].iter().any(|&cap| self.ti.strings.get(cap).is_some())
}
fn supports_color(&self) -> bool {
self.num_colors > 0 && self.supports_reset()
}
fn cursor_up(&mut self) -> Result<()> {
apply_cap(&self.ti, "cuu1", &[], &mut self.out)
}
fn delete_line(&mut self) -> Result<()> {
apply_cap(&self.ti, "dl", &[], &mut self.out)
}
fn carriage_return(&mut self) -> Result<()> {
apply_cap(&self.ti, "cr", &[], &mut self.out)
}
fn get_ref(&self) -> &T {
&self.out
}
fn get_mut(&mut self) -> &mut T {
&mut self.out
}
fn into_inner(self) -> T
where Self: Sized
{
self.out
}
}
impl<T: Write + Send> TerminfoTerminal<T> {
/// Create a new TerminfoTerminal with the given TermInfo and Write.
pub fn new_with_terminfo(out: T, terminfo: Arc<TermInfo>) -> TerminfoTerminal<T> {
let nc = if terminfo.strings.contains_key("setaf") &&
terminfo.strings.contains_key("setab") {
terminfo.numbers.get("colors").map_or(0, |&n| n)
} else {
0
};
TerminfoTerminal {
out: out,
ti: terminfo,
num_colors: nc,
}
}
/// Create a new TerminfoTerminal for the current environment with the given Write.
///
/// Returns `None` when the terminfo cannot be found or parsed.
pub fn new(out: T) -> Option<TerminfoTerminal<T>> {
TermInfo::from_env().map(move |ti| {
TerminfoTerminal::new_with_terminfo(out, Arc::new(ti))
}).ok()
}
fn dim_if_necessary(&self, color: color::Color) -> color::Color {
if color >= self.num_colors && color >= 8 && color < 16 {
color - 8
} else {
color
}
}
}
impl<T: Write> Write for TerminfoTerminal<T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.out.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.out.flush()
}
}
fn cap_for_attr(attr: Attr) -> &'static str {
match attr {
Attr::Bold => "bold",
Attr::Dim => "dim",
Attr::Italic(true) => "sitm",
Attr::Italic(false) => "ritm",
Attr::Underline(true) => "smul",
Attr::Underline(false) => "rmul",
Attr::Blink => "blink",
Attr::Standout(true) => "smso",
Attr::Standout(false) => "rmso",
Attr::Reverse => "rev",
Attr::Secure => "invis",
Attr::ForegroundColor(_) => "setaf",
Attr::BackgroundColor(_) => "setab",
}
}
fn apply_cap(ti: &TermInfo, cmd: &str, params: &[Param], out: &mut io::Write) -> Result<()> {
match ti.strings.get(cmd) {
Some(cmd) => {
match expand(cmd, params, &mut Variables::new()) {
Ok(s) => {
try!(out.write_all(&s));
Ok(())
}
Err(e) => Err(e.into()),
}
}
None => Err(Error::NotSupported),
}
}
fn reset(ti: &TermInfo, out: &mut io::Write) -> Result<()> {
// are there any terminals that have color/attrs and not sgr0?
// Try falling back to sgr, then op
let cmd = match [("sgr0", &[] as &[Param]), ("sgr", &[Param::Number(0)]), ("op", &[])]
.iter()
.filter_map(|&(cap, params)| {
ti.strings.get(cap).map(|c| (c, params))
})
.next() {
Some((op, params)) => {
match expand(op, params, &mut Variables::new()) {
Ok(cmd) => cmd,
Err(e) => return Err(e.into()),
}
}
None => return Err(Error::NotSupported),
};
try!(out.write_all(&cmd));
Ok(())
}

176
src/terminal_win.rs Normal file
View File

@@ -0,0 +1,176 @@
/*!
This module contains a Windows-only *in-memory* implementation of the
`term::Terminal` trait.
This particular implementation is a bit idiosyncratic, and the "in-memory"
specification is to blame. In particular, on Windows, coloring requires
communicating with the console synchronously as data is written to stdout.
This is anathema to how ripgrep fundamentally works: by writing search results
to intermediate thread local buffers in order to maximize parallelism.
Eliminating parallelism on Windows isn't an option, because that would negate
a tremendous performance benefit just for coloring.
We've worked around this by providing an implementation of `term::Terminal`
that records precisely where a color or a reset should be invoked, according
to a byte offset in the in memory buffer. When the buffer is actually printed,
we copy the bytes from the buffer to stdout incrementally while invoking the
corresponding console APIs for coloring at the right location.
(Another approach would be to do ANSI coloring unconditionally, then parse that
and translate it to console commands. The advantage of that approach is that
it doesn't require any additional memory for storing offsets. In practice
though, coloring is only used in the terminal, which tends to correspond to
searches that produce very few results with respect to the corpus searched.
Therefore, this is an acceptable trade off. Namely, we do not pay for it when
coloring is disabled.
*/
use std::io;
use term::{self, Terminal};
use term::color::Color;
/// An in-memory buffer that provides Windows console coloring.
#[derive(Clone, Debug)]
pub struct WindowsBuffer {
buf: Vec<u8>,
pos: usize,
colors: Vec<WindowsColor>,
}
/// A color associated with a particular location in a buffer.
#[derive(Clone, Debug)]
struct WindowsColor {
pos: usize,
opt: WindowsOption,
}
/// A color or reset directive that can be translated into an instruction to
/// the Windows console.
#[derive(Clone, Debug)]
enum WindowsOption {
Foreground(Color),
Background(Color),
Reset,
}
impl WindowsBuffer {
/// Create a new empty buffer for Windows console coloring.
pub fn new() -> WindowsBuffer {
WindowsBuffer {
buf: vec![],
pos: 0,
colors: vec![],
}
}
fn push(&mut self, opt: WindowsOption) {
let pos = self.pos;
self.colors.push(WindowsColor { pos: pos, opt: opt });
}
/// Print the contents to the given terminal.
pub fn print_stdout<T: Terminal + Send>(&self, tt: &mut T) {
if !tt.supports_color() {
let _ = tt.write_all(&self.buf);
let _ = tt.flush();
return;
}
let mut last = 0;
for col in &self.colors {
let _ = tt.write_all(&self.buf[last..col.pos]);
match col.opt {
WindowsOption::Foreground(c) => {
let _ = tt.fg(c);
}
WindowsOption::Background(c) => {
let _ = tt.bg(c);
}
WindowsOption::Reset => {
let _ = tt.reset();
}
}
last = col.pos;
}
let _ = tt.write_all(&self.buf[last..]);
let _ = tt.flush();
}
/// Clear the buffer.
pub fn clear(&mut self) {
self.buf.clear();
self.colors.clear();
self.pos = 0;
}
}
impl io::Write for WindowsBuffer {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let n = try!(self.buf.write(buf));
self.pos += n;
Ok(n)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl Terminal for WindowsBuffer {
type Output = Vec<u8>;
fn fg(&mut self, fg: Color) -> term::Result<()> {
self.push(WindowsOption::Foreground(fg));
Ok(())
}
fn bg(&mut self, bg: Color) -> term::Result<()> {
self.push(WindowsOption::Background(bg));
Ok(())
}
fn attr(&mut self, _attr: term::Attr) -> term::Result<()> {
Err(term::Error::NotSupported)
}
fn supports_attr(&self, _attr: term::Attr) -> bool {
false
}
fn reset(&mut self) -> term::Result<()> {
self.push(WindowsOption::Reset);
Ok(())
}
fn supports_reset(&self) -> bool {
true
}
fn supports_color(&self) -> bool {
true
}
fn cursor_up(&mut self) -> term::Result<()> {
Err(term::Error::NotSupported)
}
fn delete_line(&mut self) -> term::Result<()> {
Err(term::Error::NotSupported)
}
fn carriage_return(&mut self) -> term::Result<()> {
Err(term::Error::NotSupported)
}
fn get_ref(&self) -> &Vec<u8> {
&self.buf
}
fn get_mut(&mut self) -> &mut Vec<u8> {
&mut self.buf
}
fn into_inner(self) -> Vec<u8> {
self.buf
}
}

View File

@@ -8,16 +8,20 @@ use std::error::Error as StdError;
use std::fmt;
use std::path::Path;
use gitignore::{self, Gitignore, GitignoreBuilder, Match, Pattern};
use regex;
use gitignore::{Match, Pattern};
use globset::{self, GlobBuilder, GlobSet, GlobSetBuilder};
const TYPE_EXTENSIONS: &'static [(&'static str, &'static [&'static str])] = &[
("asm", &["*.asm", "*.s", "*.S"]),
("awk", &["*.awk"]),
("c", &["*.c", "*.h", "*.H"]),
("cbor", &["*.cbor"]),
("clojure", &["*.clj", "*.cljs"]),
("cmake", &["CMakeLists.txt"]),
("clojure", &["*.clj", "*.cljc", "*.cljs", "*.cljx"]),
("cmake", &["*.cmake", "CMakeLists.txt"]),
("coffeescript", &["*.coffee"]),
("config", &["*.config"]),
("cpp", &[
"*.C", "*.cc", "*.cpp", "*.cxx",
"*.h", "*.H", "*.hh", "*.hpp",
@@ -33,12 +37,16 @@ const TYPE_EXTENSIONS: &'static [(&'static str, &'static [&'static str])] = &[
"*.f", "*.F", "*.f77", "*.F77", "*.pfo",
"*.f90", "*.F90", "*.f95", "*.F95",
]),
("fsharp", &["*.fs", "*.fsx", "*.fsi"]),
("go", &["*.go"]),
("groovy", &["*.groovy"]),
("haskell", &["*.hs", "*.lhs"]),
("html", &["*.htm", "*.html"]),
("java", &["*.java"]),
("js", &["*.js"]),
("jinja", &["*.jinja", "*.jinja2"]),
("js", &[
"*.js", "*.jsx", "*.vue",
]),
("json", &["*.json"]),
("jsonl", &["*.jsonl"]),
("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
@@ -46,26 +54,34 @@ const TYPE_EXTENSIONS: &'static [(&'static str, &'static [&'static str])] = &[
("m4", &["*.ac", "*.m4"]),
("make", &["gnumakefile", "Gnumakefile", "makefile", "Makefile", "*.mk"]),
("markdown", &["*.md"]),
("md", &["*.md"]),
("matlab", &["*.m"]),
("mk", &["mkfile"]),
("ml", &["*.ml"]),
("nim", &["*.nim"]),
("objc", &["*.h", "*.m"]),
("objcpp", &["*.h", "*.mm"]),
("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]),
("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm"]),
("php", &["*.php", "*.php3", "*.php4", "*.php5", "*.phtml"]),
("py", &["*.py"]),
("rr", &["*.R"]),
("readme", &["README*", "*README"]),
("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
("rst", &["*.rst"]),
("ruby", &["*.rb"]),
("rust", &["*.rs"]),
("scala", &["*.scala"]),
("sh", &["*.bash", "*.csh", "*.ksh", "*.sh", "*.tcsh"]),
("spark", &["*.spark"]),
("sql", &["*.sql"]),
("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
("swift", &["*.swift"]),
("tex", &["*.tex", "*.cls", "*.sty"]),
("ts", &["*.ts", "*.tsx"]),
("txt", &["*.txt"]),
("toml", &["*.toml", "Cargo.lock"]),
("vala", &["*.vala"]),
("vb", &["*.vb"]),
("vimscript", &["*.vim"]),
("xml", &["*.xml"]),
("yacc", &["*.y"]),
@@ -81,7 +97,9 @@ pub enum Error {
/// A user specified file type definition could not be parsed.
InvalidDefinition,
/// There was an error building the matcher (probably a bad glob).
Gitignore(gitignore::Error),
Glob(globset::Error),
/// There was an error compiling a glob as a regex.
Regex(regex::Error),
}
impl StdError for Error {
@@ -89,7 +107,8 @@ impl StdError for Error {
match *self {
Error::UnrecognizedFileType(_) => "unrecognized file type",
Error::InvalidDefinition => "invalid definition",
Error::Gitignore(ref err) => err.description(),
Error::Glob(ref err) => err.description(),
Error::Regex(ref err) => err.description(),
}
}
}
@@ -104,14 +123,21 @@ impl fmt::Display for Error {
write!(f, "invalid definition (format is type:glob, e.g., \
html:*.html)")
}
Error::Gitignore(ref err) => err.fmt(f),
Error::Glob(ref err) => err.fmt(f),
Error::Regex(ref err) => err.fmt(f),
}
}
}
impl From<gitignore::Error> for Error {
fn from(err: gitignore::Error) -> Error {
Error::Gitignore(err)
impl From<globset::Error> for Error {
fn from(err: globset::Error) -> Error {
Error::Glob(err)
}
}
impl From<regex::Error> for Error {
fn from(err: regex::Error) -> Error {
Error::Regex(err)
}
}
@@ -137,7 +163,9 @@ impl FileTypeDef {
/// Types is a file type matcher.
#[derive(Clone, Debug)]
pub struct Types {
gi: Option<Gitignore>,
defs: Vec<FileTypeDef>,
selected: Option<GlobSet>,
negated: Option<GlobSet>,
has_selected: bool,
unmatched_pat: Pattern,
}
@@ -149,14 +177,21 @@ impl Types {
///
/// If has_selected is true, then at least one file type was selected.
/// Therefore, any non-matches should be ignored.
fn new(gi: Option<Gitignore>, has_selected: bool) -> Types {
fn new(
selected: Option<GlobSet>,
negated: Option<GlobSet>,
has_selected: bool,
defs: Vec<FileTypeDef>,
) -> Types {
Types {
gi: gi,
defs: defs,
selected: selected,
negated: negated,
has_selected: has_selected,
unmatched_pat: Pattern {
from: Path::new("<filetype>").to_path_buf(),
original: "<none>".to_string(),
pat: "<none>".to_string(),
original: "<N/A>".to_string(),
pat: "<N/A>".to_string(),
whitelist: false,
only_dir: false,
},
@@ -165,7 +200,7 @@ impl Types {
/// Creates a new file type matcher that never matches.
pub fn empty() -> Types {
Types::new(None, false)
Types::new(None, None, false, vec![])
}
/// Returns a match for the given path against this file type matcher.
@@ -175,22 +210,40 @@ impl Types {
/// If at least one file type is selected and path doesn't match, then
/// the path is also considered ignored.
pub fn matched<P: AsRef<Path>>(&self, path: P, is_dir: bool) -> Match {
// If we don't have any matcher, then we can't do anything.
if self.negated.is_none() && self.selected.is_none() {
return Match::None;
}
// File types don't apply to directories.
if is_dir {
return Match::None;
}
let path = path.as_ref();
self.gi.as_ref()
.map(|gi| {
let path = &*path.to_string_lossy();
let mat = gi.matched_utf8(path, is_dir).invert();
if self.has_selected && mat.is_none() {
Match::Ignored(&self.unmatched_pat)
} else {
mat
}
})
.unwrap_or(Match::None)
let name = match path.file_name() {
Some(name) => name.to_string_lossy(),
None if self.has_selected => {
return Match::Ignored(&self.unmatched_pat);
}
None => {
return Match::None;
}
};
if self.negated.as_ref().map(|s| s.is_match(&*name)).unwrap_or(false) {
return Match::Ignored(&self.unmatched_pat);
}
if self.selected.as_ref().map(|s|s.is_match(&*name)).unwrap_or(false) {
return Match::Whitelist(&self.unmatched_pat);
}
if self.has_selected {
Match::Ignored(&self.unmatched_pat)
} else {
Match::None
}
}
/// Return the set of current file type definitions.
pub fn definitions(&self) -> &[FileTypeDef] {
&self.defs
}
}
@@ -198,8 +251,8 @@ impl Types {
/// a set of file type selections.
pub struct TypesBuilder {
types: HashMap<String, Vec<String>>,
select: Vec<String>,
select_not: Vec<String>,
selected: Vec<String>,
negated: Vec<String>,
}
impl TypesBuilder {
@@ -207,41 +260,64 @@ impl TypesBuilder {
pub fn new() -> TypesBuilder {
TypesBuilder {
types: HashMap::new(),
select: vec![],
select_not: vec![],
selected: vec![],
negated: vec![],
}
}
/// Build the current set of file type definitions *and* selections into
/// a file type matcher.
pub fn build(&self) -> Result<Types, Error> {
if self.select.is_empty() && self.select_not.is_empty() {
return Ok(Types::new(None, false));
}
let mut bgi = GitignoreBuilder::new("/");
for name in &self.select {
let globs = match self.types.get(name) {
Some(globs) => globs,
None => {
return Err(Error::UnrecognizedFileType(name.to_string()));
let selected_globs =
if self.selected.is_empty() {
None
} else {
let mut bset = GlobSetBuilder::new();
for name in &self.selected {
let globs = match self.types.get(name) {
Some(globs) => globs,
None => {
let msg = name.to_string();
return Err(Error::UnrecognizedFileType(msg));
}
};
for glob in globs {
let pat = try!(
GlobBuilder::new(glob)
.literal_separator(true).build());
bset.add(pat);
}
}
Some(try!(bset.build()))
};
for glob in globs {
try!(bgi.add("<filetype>", glob));
}
}
for name in &self.select_not {
let globs = match self.types.get(name) {
Some(globs) => globs,
None => {
return Err(Error::UnrecognizedFileType(name.to_string()));
let negated_globs =
if self.negated.is_empty() {
None
} else {
let mut bset = GlobSetBuilder::new();
for name in &self.negated {
let globs = match self.types.get(name) {
Some(globs) => globs,
None => {
let msg = name.to_string();
return Err(Error::UnrecognizedFileType(msg));
}
};
for glob in globs {
let pat = try!(
GlobBuilder::new(glob)
.literal_separator(true).build());
bset.add(pat);
}
}
Some(try!(bset.build()))
};
for glob in globs {
try!(bgi.add("<filetype>", &format!("!{}", glob)));
}
}
Ok(Types::new(Some(try!(bgi.build())), !self.select.is_empty()))
Ok(Types::new(
selected_globs,
negated_globs,
!self.selected.is_empty(),
self.definitions(),
))
}
/// Return the set of current file type definitions.
@@ -260,14 +336,30 @@ impl TypesBuilder {
}
/// Select the file type given by `name`.
///
/// If `name` is `all`, then all file types are selected.
pub fn select(&mut self, name: &str) -> &mut TypesBuilder {
self.select.push(name.to_string());
if name == "all" {
for name in self.types.keys() {
self.selected.push(name.to_string());
}
} else {
self.selected.push(name.to_string());
}
self
}
/// Ignore the file type given by `name`.
pub fn select_not(&mut self, name: &str) -> &mut TypesBuilder {
self.select_not.push(name.to_string());
///
/// If `name` is `all`, then all file types are negated.
pub fn negate(&mut self, name: &str) -> &mut TypesBuilder {
if name == "all" {
for name in self.types.keys() {
self.negated.push(name.to_string());
}
} else {
self.negated.push(name.to_string());
}
self
}
@@ -333,7 +425,7 @@ mod tests {
btypes.select(sel);
}
for selnot in $selnot {
btypes.select_not(selnot);
btypes.negate(selnot);
}
let types = btypes.build().unwrap();
let mat = types.matched($path, false);

View File

@@ -26,6 +26,7 @@ impl Iter {
}
/// Returns true if this entry should be skipped.
#[inline(always)]
fn skip_entry(&self, ent: &DirEntry) -> bool {
if ent.depth() == 0 {
// Never skip the root directory.
@@ -41,6 +42,7 @@ impl Iter {
impl Iterator for Iter {
type Item = DirEntry;
#[inline(always)]
fn next(&mut self) -> Option<DirEntry> {
while let Some(ev) = self.it.next() {
match ev {
@@ -108,6 +110,7 @@ impl From<WalkDir> for WalkEventIter {
impl Iterator for WalkEventIter {
type Item = walkdir::Result<WalkEvent>;
#[inline(always)]
fn next(&mut self) -> Option<walkdir::Result<WalkEvent>> {
let dent = self.next.take().or_else(|| self.it.next());
let depth = match dent {
@@ -135,8 +138,3 @@ impl Iterator for WalkEventIter {
}
}
}
fn is_hidden(ent: &DirEntry) -> bool {
ent.depth() > 0 &&
ent.file_name().to_str().map(|s| s.starts_with(".")).unwrap_or(false)
}

24
tests/hay.rs Normal file
View File

@@ -0,0 +1,24 @@
pub const SHERLOCK: &'static str = "\
For the Doctor Watsons of this world, as opposed to the Sherlock
Holmeses, success in the province of detective work must always
be, to a very large extent, the result of luck. Sherlock Holmes
can extract a clew from a wisp of straw or a flake of cigar ash;
but Doctor Watson has to have it taken out for him and dusted,
and exhibited clearly, with a label attached.
";
pub const CODE: &'static str = "\
extern crate snap;
use std::io;
fn main() {
let stdin = io::stdin();
let stdout = io::stdout();
// Wrap the stdin reader in a Snappy reader.
let mut rdr = snap::Reader::new(stdin.lock());
let mut wtr = stdout.lock();
io::copy(&mut rdr, &mut wtr).expect(\"I/O operation failed\");
}
";

1028
tests/tests.rs Normal file

File diff suppressed because it is too large Load Diff

217
tests/workdir.rs Normal file
View File

@@ -0,0 +1,217 @@
use std::env;
use std::error;
use std::fmt;
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process;
use std::str::FromStr;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use std::thread;
use std::time::Duration;
static TEST_DIR: &'static str = "ripgrep-tests";
static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
/// WorkDir represents a directory in which tests are run.
///
/// Directories are created from a global atomic counter to avoid duplicates.
#[derive(Debug)]
pub struct WorkDir {
/// The directory in which this test executable is running.
root: PathBuf,
/// The directory in which the test should run. If a test needs to create
/// files, they should go in here.
dir: PathBuf,
}
impl WorkDir {
/// Create a new test working directory with the given name. The name
/// does not need to be distinct for each invocation, but should correspond
/// to a logical grouping of tests.
pub fn new(name: &str) -> WorkDir {
let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);
let root = env::current_exe().unwrap()
.parent().expect("executable's directory").to_path_buf();
let dir = root.join(TEST_DIR).join(name).join(&format!("{}", id));
nice_err(&dir, repeat(|| fs::create_dir_all(&dir)));
WorkDir {
root: root,
dir: dir,
}
}
/// Create a new file with the given name and contents in this directory.
pub fn create<P: AsRef<Path>>(&self, name: P, contents: &str) {
let path = self.dir.join(name);
let mut file = nice_err(&path, File::create(&path));
nice_err(&path, file.write_all(contents.as_bytes()));
nice_err(&path, file.flush());
}
/// Remove a file with the given name from this directory.
pub fn remove<P: AsRef<Path>>(&self, name: P) {
let path = self.dir.join(name);
nice_err(&path, fs::remove_file(&path));
}
/// Create a new directory with the given path (and any directories above
/// it) inside this directory.
pub fn create_dir<P: AsRef<Path>>(&self, path: P) {
let path = self.dir.join(path);
nice_err(&path, repeat(|| fs::create_dir_all(&path)));
}
/// Creates a new command that is set to use the ripgrep executable in
/// this working directory.
pub fn command(&self) -> process::Command {
let mut cmd = process::Command::new(&self.bin());
cmd.current_dir(&self.dir);
cmd
}
/// Returns the path to the ripgrep executable.
pub fn bin(&self) -> PathBuf {
self.root.join("rg")
}
/// Returns the path to this directory.
pub fn path(&self) -> &Path {
&self.dir
}
/// Creates a directory symlink to the src with the given target name
/// in this directory.
#[cfg(not(windows))]
pub fn link_dir<S: AsRef<Path>, T: AsRef<Path>>(&self, src: S, target: T) {
use std::os::unix::fs::symlink;
let src = self.dir.join(src);
let target = self.dir.join(target);
let _ = fs::remove_file(&target);
nice_err(&target, symlink(&src, &target));
}
/// Creates a directory symlink to the src with the given target name
/// in this directory.
#[cfg(windows)]
pub fn link_dir<S: AsRef<Path>, T: AsRef<Path>>(&self, src: S, target: T) {
use std::os::windows::fs::symlink_dir;
let src = self.dir.join(src);
let target = self.dir.join(target);
let _ = fs::remove_dir(&target);
nice_err(&target, symlink_dir(&src, &target));
}
/// Creates a file symlink to the src with the given target name
/// in this directory.
#[cfg(not(windows))]
pub fn link_file<S: AsRef<Path>, T: AsRef<Path>>(
&self,
src: S,
target: T,
) {
self.link_dir(src, target);
}
/// Creates a file symlink to the src with the given target name
/// in this directory.
#[cfg(windows)]
pub fn link_file<S: AsRef<Path>, T: AsRef<Path>>(
&self,
src: S,
target: T,
) {
use std::os::windows::fs::symlink_file;
let src = self.dir.join(src);
let target = self.dir.join(target);
let _ = fs::remove_file(&target);
nice_err(&target, symlink_file(&src, &target));
}
/// Runs and captures the stdout of the given command.
///
/// If the return type could not be created from a string, then this
/// panics.
pub fn stdout<E: fmt::Debug, T: FromStr<Err=E>>(
&self,
cmd: &mut process::Command,
) -> T {
let o = self.output(cmd);
let stdout = String::from_utf8_lossy(&o.stdout);
match stdout.parse() {
Ok(t) => t,
Err(err) => {
panic!("could not convert from string: {:?}\n\n{}", err, stdout);
}
}
}
/// Gets the output of a command. If the command failed, then this panics.
pub fn output(&self, cmd: &mut process::Command) -> process::Output {
let o = cmd.output().unwrap();
if !o.status.success() {
let suggest =
if o.stderr.is_empty() {
"\n\nDid your search end up with no results?".to_string()
} else {
"".to_string()
};
panic!("\n\n==========\n\
command failed but expected success!\
{}\
\n\ncommand: {:?}\
\ncwd: {}\
\n\nstatus: {}\
\n\nstdout: {}\
\n\nstderr: {}\
\n\n==========\n",
suggest, cmd, self.dir.display(), o.status,
String::from_utf8_lossy(&o.stdout),
String::from_utf8_lossy(&o.stderr));
}
o
}
/// Runs the given command and asserts that it resulted in an error exit
/// code.
pub fn assert_err(&self, cmd: &mut process::Command) {
let o = cmd.output().unwrap();
if o.status.success() {
panic!("\n\n===== {:?} =====\n\
command succeeded but expected failure!\
\n\ncwd: {}\
\n\nstatus: {}\
\n\nstdout: {}\n\nstderr: {}\
\n\n=====\n",
cmd, self.dir.display(), o.status,
String::from_utf8_lossy(&o.stdout),
String::from_utf8_lossy(&o.stderr));
}
}
}
fn nice_err<P: AsRef<Path>, T, E: error::Error>(
path: P,
res: Result<T, E>,
) -> T {
match res {
Ok(t) => t,
Err(err) => {
panic!("{}: {:?}", path.as_ref().display(), err);
}
}
}
fn repeat<F: FnMut() -> io::Result<()>>(mut f: F) -> io::Result<()> {
let mut last_err = None;
for _ in 0..10 {
if let Err(err) = f() {
last_err = Some(err);
thread::sleep(Duration::from_millis(500));
} else {
return Ok(());
}
}
Err(last_err.unwrap())
}