4

我正在尝试编写一个 bash 函数来按其编号返回特定的管道输出行。目前完整的命令如下所示:

mdfind 'my_search_string' | sed "2q;d"

这将返回 mdfind 命令的第二行输出。

我试图sed "$1q;d"变成一个被分配为别名的函数。

如何处理管道输入?

4

4 回答 4

7

要返回第二行输出,请执行以下操作:

... | 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
于 2013-09-03T13:33:12.610 回答
2

您只需要保护变量名:

定义一个名为 search 的函数:

search() { ... | sed -n "${1}p;q"; }

但请注意,这不是便携式sed的。这样做会更好

search() { ... | sed -n "${1}{p; q;}"; }

确实,原来的 sed 不仅不可移植,而且不能做你想做的事!它应该始终在处理第 1 行后退出。如果您的sed行为与问题陈述中描述的一样,您可能需要仔细检查!

于 2013-09-03T14:06:17.790 回答
0

我的 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

(参见关于awkvs的评论sed

于 2013-09-03T14:16:46.597 回答
0

作为练习——这个版本是纯 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 版本通常会在较短的输入流中更快(或在从长流中选择早期行时),但在较长的输入流中较慢。

于 2013-09-03T14:21:49.653 回答