4

I have lots of functions in my bashrc, but for newly created ones I often forget the name of the function.

So for example, when I have defined this function in my .bashrc:

function gitignore-unstaged
{
    ### Description:
    # creates a gitignore file with every file currently not staged/commited.
    # (except the gitingore file itself)
    ### Args: -

    git ls-files --others | grep --invert-match '.gitignore' > ./.gitignore

}

And I would like to have another function which prints out the definition of the function like:

$ grepfunctions "gitignore"
function gitignore-unstaged
{
    ### Description:
    # creates a gitignore file with every file currently not staged/commited.
    # (except the gitingore file itself)
    ### Args: -

    git ls-files --others | grep --invert-match '.gitignore' > ./.gitignore
}

But instead of matching for "gitignore" I want it to match every string between funtction and }, so $ grepfunctions "###" and $ grepfunctions "creates" should output the exact same thing. That's also the reason, why declare -f and such don't solve the problem.

What I have tried

  • I can't use grep
  • I know, that sed -n -e '/gitignore-unstaged/,/^}/p' ~/.bashrc prints out what i want - but sed -n -e '/creates/,/^}/p' ~/.bashrc not. Instead, I receive:

        # creates a gitignore file with every file currently not staged/commited.
        # (except the gitingore file itself)
        ### Args: -
    
        git ls-files --others | grep --invert-match '.gitignore' > ./.gitignore
    }
    

    The function name and the first { are cut out, which is not what I want.

How can I print out the complete function declaration of any function which has a specific string inside it? Of course, other tools than sed are also allowed.

  • @Theophrastus i guess you mean type -f functionname ?. 1) i sometimes don't know the exact function name. 2) Sometimes, i don't know anything from the function name, just something from the body. – toogley Nov 8 '16 at 16:51
  • @Theophrastus i don't have nested functions. I'm completely fine with a parsing approach (using sth like sed or grep or whatever). I just don't know how I could solve this. That means, i don't know how to correctly approach this problem. – toogley Nov 8 '16 at 16:56
  • Would you need to match on the comments in the function, or just the code? – thrig Nov 8 '16 at 16:59
  • @thrig. also on the comments. Basically everything in between the word function and the last } of this particular function. – toogley Nov 8 '16 at 17:00
  • @Theophrastus this doesn't solve my problem. Its the exact same output as my sed partial-solution. You didn't consider the second point of my "What i have tried" section. – toogley Nov 8 '16 at 17:03
5

Note that with zsh, you can do:

 printf '%s() {\n%s\n}\n\n' ${(kv)functions[(R)*gitignore*]}

To retrieve the information from the currently defined functions (that doesn't include the comments obviously).

Now, if you want to extract the information from the source file, then you can't do reliably unless you implement a full shell parser.

If you can make some assumption on how your functions are declared, like for instance if you always use that ksh-style function definition, with function and } at the start of the line, you could do:

perl -l -0777 -ne 'for (/^function .*?^\}$/gms) {
  print if /gitignore/}' ~/.bashrc

or to only look in the function body:

perl -l -0777 -ne 'for (/^function .*?^\}$/gms) {
  print if /\{.*gitignore/s}' ~/.bashrc
  • your first perl solution works - but your second doesn't. That means, when i execute perl -l -0777 -ne 'for (/^function .*?^\}$/gms) {print if /\{.*gitignore/}' .dotfiles/zsh/functions.zsh (i just used .bashrc to simplify my problem), nothing is printed out. – toogley Nov 8 '16 at 17:17
  • @toogley. Sorry, forgot the s flag so . matches on newline. See editt. – Stéphane Chazelas Nov 8 '16 at 17:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.