Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

--output like Ack (or: rethink --replace) #308

Closed
mernen opened this issue Jan 8, 2017 · 5 comments
Closed

--output like Ack (or: rethink --replace) #308

mernen opened this issue Jan 8, 2017 · 5 comments
Labels
doc An issue with or an improvement to documentation.

Comments

@mernen
Copy link
Contributor

mernen commented Jan 8, 2017

First, a question: what exactly is the use case for --replace? I don't think I've ever seen any other tool offering this option, and I can't think of many uses.

I do, though, find Ack's --output useful every now and then. It's a similar feature, but it replaces the contents of the entire line rather than only the matched part. When coupled with -h (hiding line numbers and file names), it allows one to pipe the results to other tools to get statistics about the matches in ways I'm not sure how I'd achieve with ripgrep (or other competitors, for that matter).

$ # what are the std modules in use?
$ ack '\bstd::\w+' --output '$&' -h | sort | uniq -c | sort -nr
  29 std::path
  28 std::io
  18 std::os
  16 std::sync
  14 std::ffi
  10 std::error
   9 std::fs
   9 std::fmt
   7 std::str
   6 std::env
   5 std::cmp
   4 std::thread
   4 std::process
   4 std::mem
   4 std::collections
   3 std::borrow
   2 std::time
   2 std::result
   2 std::ops
   2 std::cell
   1 std::vec
   1 std::slice
   1 std::marker
   1 std::iter
   1 std::hash
   1 std::ascii

(ripgrep's --replace can be fully emulated in Ack using $` and $' in the output expression, but those perlisms are rather cryptic, and also pretty awkward to use on the CLI)

@BurntSushi
Copy link
Owner

Ack's --output is isomorphic to ripgrep's --replace. Apparently, it works slightly differently. As you noticed, it enables one to replace each match if they want to. At the same time, it's pretty easy to replace the entire line as well. All you need to do is make the regex match the full line. So \bstd::\w+ would be written as ^.*\bstd::\w+.*$. To use --replace, you'd then want to create a capturing group as well. So, ripgrep's version of your ack command is:

$ rg '^.*(\bstd::\w+).*$' --replace '$1' --no-filename | sort | uniq -c | sort -nr

Which has the same output. The --no-filename is like ack's -h flag.

(ripgrep's --replace can be fully emulated in Ack using $` and $' in the output pattern, but those perlisms are rather cryptic, and also pretty awkward to use on the CLI)

Hmm, yes, I'm actually not familiar with those perlisms. :-)

@mernen
Copy link
Contributor Author

mernen commented Jan 8, 2017

Huh, indeed, it didn't occur to me at all to use ^.* and .*$ to replace the full line.

Since they are fully isomorphic, if there's no intention to change how --replace works, I suppose this issue should be closed — even though I still find --output more useful (i.e. simpler on the more common use case), I don't think it's a good idea to have both, and I can certainly live just with --replace.

@BurntSushi
Copy link
Owner

Yeah, I can see how --output might be more convenient. Tricky issue.

I think we can at least improve the docs of --replace to include an example that replaces the entire line.

@BurntSushi BurntSushi added the doc An issue with or an improvement to documentation. label Jan 9, 2017
@mernen
Copy link
Contributor Author

mernen commented Jan 9, 2017

Just saw #34, about the grep feature --only-matching. I think it'd be the best of all worlds:

  • As far as I can see, -or would be equivalent to Ack's --output
  • The alternative use case (today's --replace) would still be available, and significantly less cryptic and annoying to type than Ack's --output '$`expr'"$'"
  • -o is a grep standard and works with other matches. I did consider adding a flag, but it seemed quite ridiculous to have one just for --replace. It didn't occur to me this same flag could have other (natural) uses.

@BurntSushi
Copy link
Owner

@mernen Good point. It actually didn't occur to me that --only-matching would be combined with --replace like that, but it makes perfect sense!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc An issue with or an improvement to documentation.
Projects
None yet
Development

No branches or pull requests

2 participants