使用 grep 的基本示例(请注意,grep 不是我唯一的用例):
$ grep -Irl "foo"
path/to/directory/help.js
path/to/directory/config.js
path/to/directory/task.js
现在我想config.js
在 Vi 中打开该文件。我的常规方法是:
$ vi path/to/directory/config.js
我必须在制表符补全的帮助下手动输入,或者从 grep 结果中突出显示文件名并复制/粘贴它。
但我希望能够通过指定它是 grep 命令中的第二个结果来 Vi 该文件。因此,类似这样的操作:
$ grep -Irl "foo" | xargs vi 2
显然 xargs 不会这样工作,这只是一个例子。但我试图找到是否有办法使用 xargs(或任何其他实用程序)来实现这一点,但我没有找到。
一位队友向我建议一起使用head
和tail
,就像这样:
$ grep -Irl "foo" | tail -n 1 | xargs vi
将检索 task.js,并且
$ grep -Irl "foo" | head -n 2 | tail -n 1 | xargs vi
将检索 config.js。想知道是否有更简洁的方法。
答案1
怎么样
vi $( grep -IrL "foo" | awk "NR==3" )
这使用 AWK 来查找适当的行。然后将输出用作 vi 的命令行参数。
我是老派的,所以我更喜欢同等的,但稍微不满意的版本-
vi ` grep -IrL "foo" | awk "NR==3" `
答案2
这与要求的并不完全一致,因为它不使用管道进入 vi,而是使用sed:
vi $( grep -Irl "foo" | sed -n '2 p')
答案3
为此,我编写了一个包装函数,如果您想重用命令的输出行,可以使用它。
首先是狂欢:
catch() {
out="$($@)"
nl <<< "$out"
read -a r -d '\n' <<< "$out"
r=("dummy" "${r[@]}")
}
然后对于嘚:
catch () {
out="$($@)"
nl <<< "$out"
r=("${(@f)out}")
}
两种变体的用法相同。首先,运行所需的命令,并在前面加上抓住,它将以漂亮的编号形式显示命令的输出:
$ catch grep -Irl "foo"
1 path/to/dir/task.js
2 path/to/dir/help.js
3 path/to/dir/config.js
$
现在,您可以使用数组参数重复使用以下命令中的任意行$r
,例如
$ wc -c ${r[2]}
14044 path/to/dir/help.js
在嘚你可以省略花括号 ( wc -c $r[2]
),但在狂欢不幸的是你需要它们。
我想到了一些注意事项:
- 仅在命令完成后才显示输出
- 输出中的奇怪字符可能会产生不稳定的行为(例如文件名中的换行符)
- 仅捕获到 STDOUT 的输出(如果某些输出写入 STDERR,它将在控制台上分离并被忽略
$r
)