CDu*_*Duv 10 bash shell nested pipe command-line-arguments
我正在寻找一种方法来使用命令的输出(比如command1)作为另一个命令的参数(比如command2).
我在尝试grep输出who命令时遇到了这个问题,但是使用了另一组命令给出的模式(实际上是tty管道输出sed).
如果tty显示:
/dev/pts/5
Run Code Online (Sandbox Code Playgroud)
并who显示:
root pts/4 2012-01-15 16:01 (xxxx)
root pts/5 2012-02-25 10:02 (yyyy)
root pts/2 2012-03-09 12:03 (zzzz)
Run Code Online (Sandbox Code Playgroud)
我只想就行了(S)"PTS/5"所以我通过管道输送tty到sed如下:
$ tty | sed 's/\/dev\///'
pts/5
Run Code Online (Sandbox Code Playgroud)
尝试的以下命令不起作用:
$ who | grep $(echo $(tty) | sed 's/\/dev\///')"
Run Code Online (Sandbox Code Playgroud)
我发现以下工作正常:
$ eval "who | grep $(echo $(tty) | sed 's/\/dev\///')"
Run Code Online (Sandbox Code Playgroud)
但我确信eval可以避免使用.
作为最后的一个节点:我注意到"-m"参数给who了我我想要的东西(只获得who与当前用户链接的那一行).但我仍然很好奇如何将管道和命令嵌套组合起来......
gho*_*oti 10
通常使用xargs使一个命令的输出成为另一个命令的选项.例如:
$ cat command1
#!/bin/sh
echo "one"
echo "two"
echo "three"
$ cat command2
#!/bin/sh
printf '1 = %s\n' "$1"
$ ./command1 | xargs -n 1 ./command2
1 = one
1 = two
1 = three
$
Run Code Online (Sandbox Code Playgroud)
但是......虽然这是你的问题,但这并不是你真正想知道的.
如果您不介意将tty存储在变量中,可以使用bash变量修改来进行替换:
$ tty=`tty`; who | grep -w "${tty#/dev/}"
ghoti pts/198 Mar 8 17:01 (:0.0)
Run Code Online (Sandbox Code Playgroud)
(你想要-w因为如果你在pts/6上你不应该看到pts/60的登录.)
您只能在变量中执行此操作,因为如果您尝试将tty命令放入管道,它会认为它不再与终端关联运行.
$ true | echo `tty | sed 's:/dev/::'`
not a tty
$
Run Code Online (Sandbox Code Playgroud)
请注意,到目前为止,此答案中没有任何内容特定于bash.由于您正在使用bash,另一种解决此问题的方法是使用进程替换.例如,虽然这不起作用:
$ who | grep "$(tty | sed 's:/dev/::')"
Run Code Online (Sandbox Code Playgroud)
这样做:
$ grep $(tty | sed 's:/dev/::') < <(who)
Run Code Online (Sandbox Code Playgroud)
@ Eduardo的答案是正确的(当我写这篇文章时,已经出现了几个其他好的答案),但我想解释原始命令失败的原因.像往常一样,set -x看看实际发生的事情非常有用:
$ set -x
$ who | grep $(echo $(tty) | sed 's/\/dev\///')
+ who
++ sed 's/\/dev\///'
+++ tty
++ echo not a tty
+ grep not a tty
grep: a: No such file or directory
grep: tty: No such file or directory
Run Code Online (Sandbox Code Playgroud)
在上面并没有完全明确,但正在发生的tty是输出"不是tty".这是因为它是输出输出的管道的一部分who,所以它的标准输入确实不是tty.这是其他人的答案工作的真正原因:他们tty离开了管道,所以它可以看到你的实际终端.
顺便说一句,您提出的命令基本上是正确的(管道问题除外),但不必要的复杂.不要使用echo $(tty),它基本上和刚才一样tty.
你可以在不借助于Bash变量修改的情况下使用sed来做到这一点,尽管@ruakh指出这在单行版本中不起作用(没有用分号分隔命令).我要离开这第一个方法了,因为我认为有趣的是它不能在一行中起作用:
TTY=$(tty); who | grep "${TTY#/dev/}"
Run Code Online (Sandbox Code Playgroud)
首先将输出tty放入变量中,然后删除/dev/grep使用它的前导.但是,如果没有分号TTY是不是由那一刻的bash环境确实变扩建/重整grep的.
这是一个可行的版本,因为它使用已修改的环境生成子shell(具有TTY):
TTY=$(tty) WHOLINE=$(who | grep "${TTY#/dev/}")
Run Code Online (Sandbox Code Playgroud)
结果留在了$WHOLINE.
| 归档时间: |
|
| 查看次数: |
25908 次 |
| 最近记录: |