Follow

Tried to look into in to capture two terms, and I still don't get it. The manual seems to list all the commands in emacs but there aren't a lot of examples as to how to use them. It says to use grep as you'd use it in the shell, but I can't pipe grep the same way (unless I use shell inside emacs, which is not the point).

So, any good rgrep examples out there?

@kensanata I'm tagging you since this will also be good in the wiki? @eludom you started it :-)

@kensanata @eludom a d while I'm at it. There's also Occur, which I haven't used much. What about this one, if you're looking for certain terms through non-agenda-file org files? (So you can't use org-agenda to search)

@kensanata @eludom oh ok. I think that's where you said you can't pipe it like you would in shell, right?

So best I can do at this point is to use occur to filter on top of that, or (didn't try) another grep on the grep I just ran. This works also.

@jtr Not sure exactly what you're trying to do, but ripgrep with consult is a pretty good combination. I use it to search my Denote (formerly Org-roam) files baty.net/2022/searching-org-ro

@jackbaty examples for rgrep usage to look for two worlds or more at once.

@jtr Interestingly, using -e twice seems to work as an OR with M-x find-grep. How strange.
find . -name "*.md" -type f -exec grep --color -niH -e foo -e bar /dev/null \{\} +

@kensanata @jtr isn't that normal behavior of grep? Search for multiple patterns with -e <pattern1> -e <pattern2> ?

@linm Yeah, I just didn't know that you could use -e multiple times
@jtr

@kensanata @linm so seems like -e "term1" -e "term2" will give me term1 OR term2. What of "term1" AND "term2"?

Alex, using Occur on the results work for that as an additional filter, thanks for that trick.

There are quite a few ways to get to the results, and I'm trying to at least be familiar with a couple to get a better understanding of this as a general concept.

Thanks! Sorry for not being able to answer quickly enough, I get pulled away to things :/

@jtr @linm multiple terms that must match at the same time means running multiple greps; in one command, find/grep is the answer: find STARTING-DIRECTORY OPTIONS… where STARTING-DIRECTORY is often just "." and useful options include -name "*.txt" or some other glob, and -exec SOME COMMAND WITH ARGS INCLUDING {} ENDED BY ; – for example -exec grep --quiet foo "{}" ";" -exec grep --quiet bar "{}" ";" means: grep the file (in place of {}) for foo, and if that matches, grep the same file for bar; and if that also matches, do whatever comes next, e.g. -print which prints the filename.

@kensanata @linm so in this syntax you use ; to separate the commands, and essentially run the same thing again with a different pattern. It's like piping grep to another grep in the shell, yes?

Think I'm getting it... lol

@jtr Yeah, in a way. But conceptually: no! A pipe takes the output of one command (the matching lines) and uses it as input for the next command (the second grep in the pipe therefore only checks the lines that matched the first grep). With find, you need to think of it as a sequence of tests. You can test the filename against a name glob using -name, or a regular expression using -regex, or test it's type using -type (file or directory, for example), and – here it comes – you can use -exec … ";" to run a test on the filename. The argument "{}" is replaced by the filename. So if you use -exec twice, and use a grep in each case, then each grep is independent: each grep tests the entire file. Thus, in the pipe case, "foo" and "bar" need to be on the same line; in the find case, "foo" and "bar" need to be in the same file.

@linm

@kensanata @linm hmm. Ok even clearer now... brain .. expanding... :)

I need to play with it and do some searches.

Using grep in emacs is one specific solution (which I asked to be specific about and got the information). You also pointed to occur, which is something you use. There was also something ivy related, I want to explore that too.

What I do now is run rgrep for the directory, and then C-s with ivy which finds what I want from within three results.

@kensanata @linm I could also run occur in top of that, filtering it a third time. Hmm.

@jtr I can't see the original post, so the question is unclear to me. The use of rgrep is simple: M-x grep and replace grep with rgrep. If what your want is the equivalent of "grep human *.md | grep sleep" to find lines matching both human and sleep independent of order, then you're out of luck because M-x grep doesn't process this as a pipe like the shell. You'd have to write something like grep "human.*sleep\|sleep.*human" *.md. Finally, M-x rgrep has a different implementation that doesn't actually call rgrep – it calls find and grep! find […] -exec grep […] -e human […] \{\} + and so it's unclear how you'd append another grep to that command line unless you wanted to write a different implementation. Probably your best bet would be to grep for one word and then use M-x occur to filter lines for the other. Occur only works on the current buffer, so it's fine if you have a single grep buffer to search. Personally I use M-x swiper or M-x ivy-occur instead of occur, most of the time. I just found M-x swiper-multi for doing it to multiple buffers. But then… Open dired, %m md$ RET to mark the markdown files, C-u F to open them all, then M-x swiper-all … but it's still dependent on the other. Anyway, enough guessing what the real question is. 😆
@eludom

@kensanata @eludom there's a lot of good stuff here!

Ok, so my question is at basic level is, how do you search for two terms at once. To add another layer to it: search for ice cream is one thing since the words follow, but searching restaurant AND ice cream is different: I'm looking for a restaurant where I are ice cream, not sure where the word restaurant is in the text with ice cream but I know I want it included somewhere.

@jtr I guess the most important message here is that you're interested in the occurrence of two or more words anywhere in the text and not on the same line, right? Because that's what grep does: it searches for lines.

@kensanata @eludom

Now, you kind of answer that with occur, which I didn't think about. I also use ivy btw and not familiar with the others function you suggested. Do you have an example of this?

But ok. Occur will search on the active buffer, which will be the result of rgrep in our case. This is good. It's kind of like piping grep. So I will try that too.

@jtr OK, so if we're interested in finding files for which a number of grep operations return "true", we need the find command executing multiple grep commands and printing the file name when they all succeed:

~/src/spellcasters $ find . -name "*.md" -exec grep --quiet human "{}" ";" -exec grep --quiet paralysis "{}" ";" -print
./Agrimach.md
./Spells.md
./Spells-no-cover.md
./Wogan.md
./Spellcasters-no-cover.md

Let's verify this for one file:

~/src/spellcasters $ egrep "human|paralysis" Agrimach.md
Agrimach.md:51:within 24h. HD 2 AC 6 1d4/1d4/1d4 + *paralysis* F2 MV 9 ML 9; *aura of
Agrimach.md:88:limbs and extras: a human with an extra arm has a 1 in 5 chance of the

Now, if you want to run it inside Emacs, perhaps you don't want to just print the filenames (or do you?) – but if you drop the --quiet option the files where just one grep command matches aren't printed – but the one matching grep is listed. Check out the Fanthaniel.md file, for example:

M-x find-grep RET find . -name "*.md" -type f -exec grep --color -iH -e human {} \; -exec grep --color -iH -e paralysis {} \; -print RET

find . -name "*.md" -type f -exec grep --color -iH -e human \{\} \; -exec grep --color -iH -e paralysis \{\} \; -print
./Fanthaiel.md:passage of time, human settlements, monsters, idleness.
./Agrimach.md:limbs and extras: a human with an extra arm has a 1 in 5 chance of the
./Agrimach.md:**Paralysis** (2) affects one person within 30ft; they must save
./Agrimach.md:within 24h. HD 2 AC 6 1d4/1d4/1d4 + *paralysis* F2 MV 9 ML 9; *aura of
./Agrimach.md
./Jezembal.md:20ft. The wave keeps moving as fast as a human can run for as long as
./Olgana.md:**The Psalm of the Loyal Soul** (1) turns a humanoid into a standfast

Note how only the Agrimach.md actually qualifies. So perhaps what we need to do is keep the old command line and simply add yet another grep instead of -print.

M-x find-grep RET find . -name "*.md" -type f -exec grep -qi -e human {} \; -exec grep -qi -e paralysis {} \; -exec grep --color -iH -e "human|paralysis" {} \;

-e is --regexp=
-q is --quiet
-H is --with-filename

@kensanata @eludom

Finally, I am having hard time figuring out the regex. There are plenty of indexes (like it the emacs wiki) explaining what are the different operators, but I'm having hard time implementing them.

Need an example and then go backward and explain myself why it works the way it does.

@jtr In this case I'd say regex writing is not the problem, so this thread is done, right?

@kensanata I think rgrep takes regex, which I'll have to build to get the temps correctly. If it's not regex (I need time to go over what you wrote, can't at the moment) then yes :-)

@jtr well, wenn it comes to words, the word is also a regular expression that matches itself, so since your question involved words, just out the word where ever the regular expression goes and you’re good to go.

@jtr Still scratching my head: where would you put the information on the Emacs Wiki? I just read through emacswiki.org/emacs/GrepMode and there is a lot of info there… but there's no recommendation for newbies, nor any kind of if this then that discussion.

@kensanata that's exactly the issue. It gives a highlight of all the tools... But all this stuff (including the manual) count on the fact that users already know grep and know what grep -e is etc.

I wrote a draft last night for a post and I need to finish it, will put it there too. It's not complete, actually, it's just a bare bone start as to how to use m-x grep in emacs with examples. I think that's a good place to start 🙂

@jtr

Have you considered simple

M-x ! grep Hitchhiker *.org | grep galaxy

@eludom did, but I want to try q more "emacsy" way. There are many ways to do it inside emacs, it's interesting to see what people do also

@jtr There's also this (from my config)

defalias 'gf 'grep-find)

(setq grep-find-command
'("find -L . -type f -mtime -21 -name \\*.org -exec egrep -i --color -nH --null -e \\{\\} +" . 80))

@eludom hmm interesting. I need to look at the code it has some new things in it (an alias to an emacs command? It exists? Ohh!).

This can be helpful too.

@jtr yeah. Then you just type

M-x gf

or bind it to a key.

You can learn much from xah Lee xahlee.info/emacs/emacs/emacs_

Sign in to participate in the conversation
Mastodon for Tech Folks

This Mastodon instance is for people interested in technology. Discussions aren't limited to technology, because tech folks shouldn't be limited to technology either!