我正在尝试编写一个 bash 函数来按其编号返回特定的管道输出行。目前完整的命令如下所示:
mdfind 'my_search_string' | sed "2q;d"
这将返回 mdfind 命令的第二行输出。
我试图sed "$1q;d"
变成一个被分配为别名的函数。
如何处理管道输入?
要返回第二行输出,请执行以下操作:
... | sed -ne 2p
并将其用作函数:
function print_2nd_line {
sed -ne 2p
}
mdfind 'my_search_string' | print_2nd_line
您也可以选择较短的名称,如p2
您的选择。
该功能还可以自定义为能够从指定文件打印第二行,例如:
function print_2nd_line {
sed -ne 2p -- "$@"
}
print_2nd_line file
... | print_2nd_line ## Still could be used like this.
顺便说一下,更有效的版本是
sed -ne '2{p;q}'
更新
正如 Charles Duffy 所建议的,您也可以使用这种格式来实现 POSIX 兼容性。实际上它也兼容所有基于原始 System V sh 的 shell。
print_2nd_line() {
sed -ne '2{p;q}' -- "$@"
}
此外,如果您想将自定义行号传递给您的函数,您可以:
print_2nd_line() {
N=$1; shift
sed -ne "${N}{p;q}" -- "$@"
}
你可以在哪里运行它:
... | print_2nd_line 2 ## Still could be used like this.
或者
print_2nd_line 2 file
您只需要保护变量名:
定义一个名为 search 的函数:
search() { ... | sed -n "${1}p;q"; }
但请注意,这不是便携式sed
的。这样做会更好
search() { ... | sed -n "${1}{p; q;}"; }
确实,原来的 sed 不仅不可移植,而且不能做你想做的事!它应该始终在处理第 1 行后退出。如果您的sed
行为与问题陈述中描述的一样,您可能需要仔细检查!
我的 bash 别名:
alias second="awk 'FNR==2'"
cat file | second
或者
second file
所以,我不明白,你想写一个函数来获取要过滤的行数作为参数吗?您还想处理其中的管道输入以过滤掉该行吗?您的管道输入将是您的函数的参数,您可以通过$@
.
对不起,我理解 OP 想要什么 :)
正如我所知道的,他希望std
通过带有参数的 shell 函数处理输入,即
cmd | func args
所以以下工作:
function sift { awk "FNR==$1" ;}
例子:
cat file | sift 2
(参见关于awk
vs的评论sed
)
作为练习——这个版本是纯 bash 的,根本不使用任何外部工具:
return_line() {
local lineno=$1
while (( lineno > 1 )); do read; (( lineno-- )); done
read -r && printf '%s\n' "$REPLY"
}
# ...to test...
return_line 3 <<<$'one\ntwo\nthree\nfour'
# ...and yes, this works with pipelines...
printf 'one\ntwo\nthree\nfour' | return_line 3
纯 bash 版本通常会在较短的输入流中更快(或在从长流中选择早期行时),但在较长的输入流中较慢。