この `grep -v`が期待どおりに機能しないのはなぜですか?


12

grep -vクエリに関連する奇妙な問題があります。説明させてください:

私が使用する接続を表示するにはwho

$ who
harry    pts/0        2016-12-08 20:41 (192.168.0.1)
james    pts/1        2016-12-08 19:28 (192.168.0.1)
timothy  pts/2        2016-12-08 02:44 (192.168.0.1)

tty私の端末の電流はpts/0

$ tty
/dev/pts/0
$ tty | cut -f3-4 -d'/'
pts/0

を使用して自分の接続を除外しようとしましたgrep -v $(tty | cut -f3-4 -d'/')。このコマンドの期待される出力はwho、接続なしでになります。ただし、出力は最も予期しないものです。

$ who | grep -v $(tty | cut -f3-4 -d'/')
grep: a: No such file or directory
grep: tty: No such file or directory

$(...)は引用符で囲み、それは「そのようなファイルまたはディレクトリがありません」問題を修正するようです。ただし、tty(pts/0)を除外する必要がある場合でも、接続は引き続き印刷されます。

$ who | grep -v "$(tty | cut -f3-4 -d'/')"
harry    pts/0        2016-12-08 20:41 (192.168.0.1)
james    pts/1        2016-12-08 19:28 (192.168.0.1)
timothy  pts/2        2016-12-08 02:44 (192.168.0.1)

この時点で、grepクエリが誤動作している理由はまったくわかりません。


4
使用方法についてはどのようにset -x次に、あなたのコマンドを実行して、あなたが実際にしようとしているか見て...最初のgrep...
don_crissti

@don_crisstiああ、なるほど。私は実際にはgrep「ttyではない」と言っています。これを回避するにはどうすればいいですか?
多分16

回答:


18

ザカリーは問題の原因を説明しました。

あなたはそれを回避することができますが

tty=$(tty)
tty_without_dev=${tty#/dev/}
who | grep -v "$tty_without_dev"

たとえば、そのttyが含まれている場合はpts/1、を含むすべての行を除外することになりますpts/10。一部のgrep実装-wには、単語検索を行うオプションがあります

who | grep -vw pts/1

inの後に非単語文字が続かないpts/10ため、一致しませんpts/1

またはawk、次のように2番目のフィールドの正確な値でフィルタリングするために使用できます。

who | awk -v "tty=$tty_without_dev" '$2 != tty'

1つのコマンドで実行する場合:

{ who | awk -v "tty=$(tty<&3)" '$2 != substr(tty,6)'; } 3<&0

ファイル記述子3に複製され、ttyコマンド用に復元される元の標準入力。


3
1つのコマンドでそれを行う方法を考え出し、その間違いを指摘して+1。
ザカリーブレイディ

もう1つのライナー:tty | cut -f3-4 -d'/' | xargs -I % sh -c "who | grep -v %"
axxis

20

tty情報ページから。

'tty'は、標準入力に接続された端末のファイル名を出力します。標準入力が端末でない場合は、「not a tty」を出力します。

問題は、あなたの例ではttyの標準入力はパイプであり、端末ではないことです。

この例からわかります。

$ tty
/dev/pts/29
$ echo | tty 
not a tty

この問題を回避するには、次のようにします。

who | grep -wv "$(ps ax | awk "\$1 == $$ {print \$2}" )"

より高速/効率的な方法がありますが、2つのコマンドが必要です。

t=$(tty)
who|grep -wv "${t:5}"

あなたのコンピューターにログインしているのはあなただけですか?
ザカリーブレイディ

@クリストファー、変だ。したがって、who | grep -v "$(ps ax | grep "^$$" | awk '{ print $2 }')"私のボックスで期待される出力が生成され、t=$(tty) who|grep -v "${t:5}"何も生成されません。
ザカリーブレイディ

どのシェル/バージョンを使用していますか?GNU bash, version 4.1.2
ザカリーブレイディ

2
ps ax | grep "^ *$$"たとえば、シェルが123で1234が存在するなど、誤って一致する可能性があります。ps ax -otty= $$より堅牢で、1つのプロセスのみです。しかし、私は好むあなた${t:5}やステファンさん${t#/dev/}(またはsubstr(t,6)
dave_thompson_085

1
免責事項を追加しないでください。意図は称賛に値しますが、実際には答えを助けません。誰かがあなたの答えの欠陥を指摘した場合、訂正を組み込むためにあなたの答えを編集するだけです。
テルドン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.