コマンドの出力(たとえばcommand1)を別のコマンド(たとえばcommand2)の引数として使用する方法を探しています。
grep
コマンドの出力をwho
しようとしたが、別のコマンドセット(実際にはtty
はsed
にパイプされた)によって与えられたパターンを使用したときに、この問題が発生しました。
tty
が表示される場合:
/dev/pts/5
そして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)
「pts/5」に関する行だけが必要なので、次のようにtty
をsed
にパイプしました。
$ tty | sed 's/\/dev\///'
pts/5
試行された次のコマンドは機能しません:
$ who | grep $(echo $(tty) | sed 's/\/dev\///')"
私は次のことがうまく機能することを発見しました:
$ eval "who | grep $(echo $(tty) | sed 's/\/dev\///')"
ただし、eval
の使用は回避できると確信しています。
最後のサイドノードとして:who
の「-m」引数が私が望むものを正確に与えることに気づきました(現在のユーザーにリンクされているwho
の行のみを取得します)。しかし、パイプとコマンドのネストのこの組み合わせを機能させる方法については、まだ興味があります...
Bash変数のマングリング の助けを借りてsedに頼らずにこれを行うことができますが、@ ruakhが指摘しているように、これは1行バージョンでは機能しません(コマンドをセミコロンで区切ることなく)。この最初のアプローチは、1行で機能しないのは興味深いと思うので、そのままにしておきます。
TTY=$(tty); who | grep "${TTY#/dev/}"
これは、最初にtty
の出力を変数に入れ、次にgrepがそれを使用するときに先頭の/dev/
を消去します。しかし、セミコロンがないと、bashがgrepの変数展開/マングリングを実行する瞬間までに、TTY
はnotになります。
これは、すでに変更された環境(TTY
がある)でサブシェルを生成するために機能するバージョンです。
TTY=$(tty) WHOLINE=$(who | grep "${TTY#/dev/}")
結果は$WHOLINE
に残されます。
通常、 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
$
しかし...それはあなたの質問でしたが、それはあなたが本当に知りたいことではありません。
Ttyを変数に格納してもかまわない場合は、bash変数マングリングを使用して置換を行うことができます。
$ tty=`tty`; who | grep -w "${tty#/dev/}"
ghoti pts/198 Mar 8 17:01 (:0.0)
(pts/6を使用している場合、pts/60のログインは表示されないため、-wが必要です。)
tty
コマンドをパイプに入れようとすると、端末に関連付けられて実行されていないと見なされるため、これは変数での実行に制限されます。
$ true | echo `tty | sed 's:/dev/::'`
not a tty
$
これまでのところ、この回答にはbashに固有のものはないことに注意してください。 bashを使用しているので、この問題を回避する別の方法は、プロセス置換を使用することです。たとえば、これは機能しませんが、次のようになります。
$ who | grep "$(tty | sed 's:/dev/::')"
これは行います:
$ grep $(tty | sed 's:/dev/::') < <(who)
@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
_
上記では完全に明示的ではありませんが、tty
が「ttyではない」を出力していることが起こっています。これは、パイプラインの一部であり、who
の出力が供給されているため、そのstdinは実際にはttyではありません。これが、他のすべての回答が機能する本当の理由です。パイプラインからtty
を取得するため、実際の端末を確認できます。
ところで、提案されたコマンドは基本的に正しいですが(パイプラインの問題を除く)、不必要に複雑です。 echo $(tty)
は使用しないでください。基本的にはtty
と同じです。
あなたはこのようにそれを行うことができます:
tid=$(tty | sed 's#/dev/##') && who | grep "$tid"