使用与管道和globs一起使用的参数来使用Bash别名

时间:2017-11-30 14:17:17

标签: bash shell scripting command-line-arguments alias

我的bashrc文件中有一个便利功能,如下所示:

function get_pattern()
{
    grep "P1" $1 | grep -v "BUT_NOT_THIS" | awk -F":" '{print $(1)}' | sort -u
}

alias gp='get_pattern'

如果我在gp file_1.c这样的单个文件上运行它,这可以正常工作。但是我无法像find . -name "*.c" -type f | xargs gp那样运行它。我也没能像gp *.c那样运行它。我如何编写get_pattern代码,以便我可以拥有所有这些便利。

注意:我已经简化了功能以便于理解。不要期待聪明的grep / awk / sed / sort黑客或调整。问题是我有一个别名,它将文件名作为参数。希望它能够与管道一起使用,最好是使用管道。

2 个答案:

答案 0 :(得分:3)

正如专家所指出的,别名不适合您的要求。

在你的函数中,你只是将第一个参数传递给grep,就像grep "P1" $1一样。将其更改为使用所有参数,这样:

function get_pattern() {
    grep "P1" "$@" | grep -v "BUT_NOT_THIS" | awk -F":" '{print $(1)}' | sort -u
}

注意:

  • 当您将函数调用为get_pattern *.c并且存在匹配的文件时,该函数看不到*.c,它会看到匹配文件的列表。全局扩展由shell在调用函数时完成,但不在函数内部。

  • 在当前格式中,该函数不从stdin读取。因此,将另一个命令的结果输入到您的函数中可能不起作用。要使它接受stdin,您需要将第一个grep更改为:

    grep "P1" - "$@"

当您希望函数只读取文件时,这会搞乱调用。因此,以这种方式重写函数会更好:

function get_pattern() {
    if (($# > 0)); then
        # arguments passed, use them as file names to grep from
        grep_args=("$@")
    else
        # no arguments passed, grep from stdin
        grep_args=(-)
    fi
    grep "P1" "${grep_args[@]}" | grep -v "BUT_NOT_THIS" | awk -F":" '{print $(1)}' | sort -u

}

答案 1 :(得分:1)

我将专注于管道数据到xargs的问题。这不起作用,因为xargs对别名一无所知。但是,您可以有效地传递函数定义以使其工作(不可移植的解决方案,在bash和可能的其他shell中工作,但不要指望它在任何地方都可以工作)export -f

$ foo() { echo foo: $@; }
$ echo bar baz | xargs bash -c 'foo $@' _
_: foo: command not found
$ export -f foo
$ echo bar baz | xargs bash -c 'foo $@' _
foo: bar baz

我不知道用别名做任何方法,但我也不知道有任何理由使用别名。停止使用别名。