重用给定索引/行号处的最后一个命令输出

重用给定索引/行号处的最后一个命令输出
ls

显示:

entry1
entry2
entry3

如何在下一个 shell 命令中重用上述输出(不是所有条目,而是给定行的条目,例如 n)?

就像是:

vi $(!!)@3

必须意味着:

vi entry3

答案1

您不能直接重用输出:它仅作为一堆像素存储在视频内存中;或者可能在终端模拟器的内存中,但也没有方便的方法可以从那里取回它。您可以做的是再次运行该命令并捕获这次的输出。这就是作用!!

在 zsh 中,使用参数扩展标志和嵌套替换以提取所选行。或者,您可以让外部实用程序进行拆分,这样更容易键入。

vi "${${(f)$(!!)}[3]}"
vi "$(!! | awk NR==3)"

这是即使在 zsh 中也确实需要双引号的少数情况之一,否则命令的输出将被拆分为空格分隔的组件。如果空格分隔的组件没问题,那么您可以使用更短的命令:

vi ${$(!!)[3]}

答案2

从输出中提取特定行的经典方法是组合headtail命令:

LINE=3
ls | head -n $LINE | tail -n 1
  • ls命令生成初始输出,
  • head -n $LINE$LINE仅保留原始输出的第一行,
  • tail -n 1仅保留命令输出的最后一行head

最后,仅保留给定位置处的线。

因此,为了继续您的示例,假设此输出包含您需要使用 编辑的文件的名称vi,您可以通过以下语法使用此输出:

vi $(ls | head -n $LINE | tail -n 1)
vi `ls | head -n $LINE | tail -n 1`

由于其可读性,第一个是首选。第二个是与旧系统兼容的历史版本。

最后要注意的是,有时初始命令(ls本例中为简单命令)可能需要时间并消耗资源来执行。如果您需要从其输出中获取几行,请毫不犹豫地将其输出存储在变量或文件中,这样它只需执行一次:

# Using a variable:
my_ls=$(ls)
vi $(echo "$my_ls" | head -n 3 | tail -n 1)
vi $(echo "$my_ls" | head -n 26 | tail -n 1)
vi $(echo "$my_ls" | head -n 1900 | tail -n 1)

# Using a file:
ls >./my_ls
vi $(cat ./my_ls | head -n 3 | tail -n 1)
vi $(cat ./my_ls | head -n 26 | tail -n 1)
vi $(cat ./my_ls | head -n 1900 | tail -n 1)

答案3

我对 zsh 没有太多经验,但一种可能的方法可能是这样的:

$ p() { i=$1 && shift && a=("${(@f)$("$@")}") && echo "${a[$i]}" }
$ ls
entry1
entry2
entry3
$ echo $(p 3 !!)
echo $(p 3 ls)
entry3

对于bash:

$ p() { i=$1 && shift && IFS=$'\n' a=($("$@")) && echo "${a[$((i-1))]}"; }

我承认这是相当麻烦的语法并且没有错误检查。

相关内容