2

I want to make function that parses from text pasted in a terminal.

$ cat <<eof | grep --color sometext
> foo
> sometext
> sometext1
> a sometext
> asdf
> 
> eof
sometext
sometext1
a sometext

While the above works I can make neither an alias nor a function of it.

alias gsi='cat <<eof | grep --color "$1"'
gsi { cat <<eof | grep --color "$1" ; }

I thought redirections weren't executed during function definition.

1.61803
  • 1,201
  • 2
  • 15
  • 23

3 Answers3

5
alias 'gsi=<<eof grep --color'

Would work as alias is just like preprocessor text replacement, where the replacement is interpreted as shell code again.

Yours was not working as you had that "$1". With gsi file.txt replaced with cat <<eof | grep --color "$1" file.txt, then the shell carries on interpreting that command line and $1 at that point is the shell's first positional parameter which is probably empty unless you did a set something beforehand. So you'd want to remove that "$1" here. You can remove the UUOC as well.

gsi() { cat <<eof | grep --color "$1" ; }

is wrong from a syntax point of view as the eof line is missing after that cat <<eof.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • Thanks, for emending the alias. I still don't understand why `here-document` is executed during function definition. – 1.61803 Aug 15 '18 at 16:14
  • @1.61803 it's not that the heredoc is executed, it's that the function body has to be syntactically complete so that bash can understand how much of what you have given is the function, unlike aliases which are essentially simple text replacements. – muru Aug 16 '18 at 00:31
4

Your function would not be using a here-document:

gsi () {
   grep --color "$@"
}

This would enable you to pass a pattern as well as any other options to grep on the common line and grep would read from standard input.

The end of the input would be signalled by pressing Ctrl+D.

The above would possibly intermingle the pasted contents and the result from grep. To accumulate the pasted content first and then run grep, you could use something like

gsi () {
    trap 'rm -f "$buffer"' RETURN
    local buffer="$(mktemp)"
    cat >"$buffer" && grep --color "$@" "$buffer"
}

Here, the pasted output is put into a temporary file before the grep is run. The temporary file is removed when the function exits. This is approximately what bash would do behind the scenes when you paste into a here-document.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • 2
    This works, but is a bit awkward in that if the input is pasted to the terminal, it will get intermixed with output from `grep`. The here-doc works as a work-around for that, though I suppose one could wrap the `grep` within `stty -echo` and `stty echo` to hide the pasted text... – ilkkachu Aug 15 '18 at 14:38
  • @ilkkachu True, the here-document in the question would act like a temporary buffer. I'll try your suggestion and make an update when I'm in front of a computer later. – Kusalananda Aug 15 '18 at 15:03
  • @Kusalananda, ideally, I would have both pasted and `grep`ed text on screen. – 1.61803 Aug 15 '18 at 16:04
2

You mentioned you're pasting to terminal. Abandon here-doc altogether, and use a proper clipboard utility, such as xclip (or pbpaste on Mac OS X). With xclip that'd be done as

xclip -o -sel clip | grep --color 'sometext'

See also 'xclip' vs. 'xsel' on the difference between the two utilities.

Sergiy Kolodyazhnyy
  • 16,187
  • 11
  • 53
  • 104