我的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黑客或调整。问题是我有一个别名,它将文件名作为参数。希望它能够与管道一起使用,最好是使用管道。
答案 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
我不知道用别名做任何方法,但我也不知道有任何理由使用别名。停止使用别名。