Home > Mobile >  Create a chained command line in bash function
Create a chained command line in bash function

Time:10-14

I have a question: I would like to create a function that (dependantly from number of entered arguments) would create so called "cained" command line. The current code I wrote look as follow:


function ignore {
   if [ -n "$@" ] && [ "$#" > 0 ]; then
      count=$#

      if [ ${count} -eq 1 ]; then
         return "grep -iv $1"
      else
         for args in "$@" do
           ## Here should be code that would put (using pseudo code) as many "grep -iv $a | grep -iv $(a 1) | ... | grep -iv $(a n)", where the part "$(a ..) represent the placeholder of next argument"
         
        done
     fi
  fi
}

Any ideas? Thanks

CodePudding user response:

This seems horribly inefficient. A much better solution would look like grep -ive "${array[0]}" -e "${array[1]}" -e "${array[2]}" etc. Here's a simple way to build that.

# don't needlessly use Bash-only function declaration syntax
ignore () {
    local args=()
    local t
    for t; do
       args =(-e "$t")
    done
    grep -iv "${args[@]}"
}

In the end, git status | ignore foo bar baz is not a lot simpler than git status | grep -ive foo -e bar -e baz so this function might not be worth these 116 bytes (spaces included). But hopefully at least this can work to demonstrate a way to build command lines programmatically. The use of arrays is important; there is no good way to preserve quoting of already quoted values if you smash everything into a single string.

If you really wanted to build a structure of pipes, I guess a recursive function would work.

# FIXME: slow and ugly, prefer the one above
ignore_slowly () {
    if [[ $# -eq 1 ]]; then
        grep -iv "$1"
    else
        local t=$1
        shift
        grep -iv "$t" | ignore_slowly "$@"
    fi
}

But generally, you want to minimize the number of processes you create.

CodePudding user response:

Though inefficient, what you want can be done like this:

#!/bin/bash

ignore () {
    printf -v pipe 'grep -iv %q | ' "$@"
    pipe=${pipe%???} # remove trailing ' | '
    bash -c "$pipe"
}

ignore 'regex1' 'regex2' … 'regexn' < file
  •  Tags:  
  • bash
  • Related