Search code examples
bashsedescapingquoting

How to save sed statement (with quotes) in a variable for multiple calls


I have the following pipeline that I use to postprocess some text:

sed 's/error/     /g' | sed 's/\+/ /g' | tail -n +6 | ghead -n -1

I need to use this pipeline many times, so I want to save all of this in a variable so that I can easily call it later. I have tried several different ways to save the quotes (single quotes, double quotes, escaped quotes, etc.), for example:

cleanup='sed '"'"'s/error/     /g'"'"' | sed '"'"'s/\+/ /g'"'"' | tail -n +6 | ghead -n -1'

However, so far I haven't found the magic combination.

Edit ======

Apparently, my real problem was that I wasn't using eval. However, I am still interested in approaches that are more elegant than mine.


Solution

  • It would work if cleanup was a function, not a string:

    cleanup() { sed 's/error/     /g' | sed 's/\+/ /g' | tail -n +6 | ghead -n -1; }
    

    As an example:

    $ seq 8 | cleanup
    6
    7
    

    Simplification

    It looks like the pipeline can be simplified. If ghead, which I am not familiar with, is the same as the usual head, then try:

    cleanup() { sed '1,5d; $d; s/error/     /g; s/\+/ /g'; }
    

    This works as follows:

    • 1,5 d deletes lines one through 5. This replaces tail -n +6.

    • $d deletes the last line. This replaces head -n -1.

    • The two substitute commands remain the same but are combined into this single invocation of sed.

    Non-GNU sed (BSD, Mac OSX)

    The above was tested on GNU sed. NeronLeVelu reports that other sed versions may require newline characters after the delete commands. In that case, using bash's $'...' feature, try:

    cleanup() { sed $'1,5d\n $d\n s/error/     /g; s/\+/ /g'; }
    

    Or, try:

    cleanup() { sed -e '1,5d' -e '$d' -e's/error/     /g' -e 's/\+/ /g'; }