0

I have a file formatted as

abc|<hoge>
a|<foo> b|<foo> c|<foo>
family|<bar> guy|<bar>
a|<foo> comedy|<bar> show|<foo>
action|<hoge>

and want to search search strings by raw (Like "a comedy show" instead of a|<foo> comedy|<bar> show|<foo>) on emacs.

I believe using grep on lisp would be the easiest answer but I have not yet figured out how. Would someone enlighten me?

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
Shun
  • 23
  • 1
  • 5
  • `"a comedy show"` is **not** a regular expression that will match `a| comedy| show|` The utility grep contains an optional argument of `E` that stands for extended regular expressions. Your question is a little unclear, but seems to be asking how to use grep in general to search using a regular expression and also how to perform that same search using the front-end that Emacs provides for the external utility grep. You may wish to further clarify the question, and even include a tag for grep since you may be asking how to perform a particular search using that utility. – lawlist Feb 11 '15 at 22:51
  • user2283547: Do you want to search interactively in Emacs? Or do you want to see a list of all the matching results? – phils Feb 11 '15 at 22:54

1 Answers1

1

Well, grep is a separate program (which you could also use). In Emacs, you'd use the function search-forward-regexp, which you can run using either M-x (hold Meta, usually Alt key, and press x) and then type search-forward-regexp and press Return.

You'll then need to key in the regexp to search. Put simply, it seems like you want to ignore |< something >, which in Emacs's variety of regexes is:

 |<[a-z]+> 

so you might search for e.g.

 a|<[a-z]+> comedy|<[a-z]+> show|<[a-z]+>

You can create a Lisp function to convert a string this way, by splitting it on spaces and adding the regex sequences:

(defun find-string-in-funny-file (s)                        ; Define a function
  "Find a string in the file with the |<foo> things in it." ; Document its purpose
  (interactive "sString to find: ")                         ; Accept input if invoked interactively with M-x
  (push-mark)                                               ; Save the current location, so `pop-global-mark' can return here
                                                            ; (usually C-u C-SPC)
  (goto-char 0)                                             ; Start at the top of the file
  (let ((re (apply #'concat                                 ; join into one string…
                   (cl-loop 
                    for word in (split-string s " ")        ; for each word in `s'
                    collect (regexp-quote word)             ; collect that word, plus
                    collect "|<[a-z]+> "))))                ; also the regex bits to skip
    (search-forward-regexp                                  ; search for the next occurrence
     (substring re 0 (- (length re) 2)))))                  ; after removing the final space from `re'

You can explore what those functions each do in the (online) Emacs Lisp manual; for example, pick from the menu "Help→Describe→Function" or press C-h f (Control+h, then f) and type interactive (RET) for the manual's documentation of that special form.

If you paste the above (defun) into the *scratch* buffer, and position the cursor after the final ) at the end, you can press C-j to evaluate it, and the function will remain with you until you close Emacs.

If you save it in a file named something .el, you can use M-x load-file to load it again in future.

If you then load your "funny" file, and type M-x find-string-in-funny-file, it'll search your file for your string, and leave the cursor on the string. If it's not found, you'll see a message to that effect.

BUGS: The function is less than spectacular style

BRPocock
  • 13,638
  • 3
  • 31
  • 50