Bash 函数处理来自管道的输入
我正在尝试编写一个bash函数,以按其编号返回管道输出的特定行。 当前,完整命令如下所示:Bash 函数处理来自管道的输入,bash,shell,Bash,Shell,我正在尝试编写一个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_
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兼容性。实际上,它也与所有基于原始SystemV 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.
或
您只需要保护变量名: 要定义名为search的函数,请执行以下操作:
search() { ... | sed -n "${1}p;q"; }
但请注意,这不是可移植的sed
。这样做会更好
search() { ... | sed -n "${1}{p; q;}"; }
事实上,原始的sed不仅仅是不可移植的,而且不能满足您的需要!它应该总是在处理第1行之后退出。如果您有一个sed
,它的行为与您在问题陈述中描述的一样,您可能需要再次检查 我的awked bash别名:
alias second=“awk”FNR==2'
cat文件|秒
或
第二个文件
所以,我不太明白,你们想写一个函数,把要过滤的行数作为参数吗?您还想处理其中的管道输入以过滤掉该行吗?管道输入将是函数的参数,您可以通过$@
获取所有参数
对不起,我知道OP想要什么:)当我得到它时,他希望处理带有参数的shell函数输入的
std
,即
cmd | func参数
因此,以下工作:
函数筛选{awk“FNR==1”}
例如:
cat文件|筛选2
(请参见关于awk
vssed
)的注释作为练习--此版本使用纯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
返回_行(){
本地线路号=$1
当((行号>1));读;((行号-);完成
read-r&&printf“%s\n'$REPLY”
}
#…测试。。。
return_第3行只有一个诡辩--function
关键字实际上弊大于利,破坏了POSIX兼容性,却没有带来任何好处。最好省去它:print_2nd_line(){…}
@CharlesDuffy Yes对于POSIX兼容性,最好使用它。在Bash中,我实际上默认使用函数
,但在其他shell中,或者当我指的是兼容性时,使用f(){}
格式。这似乎没有响应的唯一方法是硬编码要提取的行号,当问题读作想要参数化时。使用函数比使用别名好得多——默认情况下,脚本中根本不启用别名。Awk脚本在打印后不会终止,因此对于长输入,它将比OP的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