Mengapa `grep -v` ini tidak berfungsi seperti yang diharapkan?


12

Saya memiliki masalah aneh terkait dengan grep -vpermintaan. Izinkan saya menjelaskan:

Untuk menampilkan koneksi yang saya gunakan 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)

Arus ttyterminal saya adalahpts/0

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

Saya berusaha mengecualikan koneksi saya sendiri menggunakan grep -v $(tty | cut -f3-4 -d'/'). Output yang diharapkan dari perintah ini seharusnya who, tanpa koneksi saya. Namun, outputnya paling tak terduga:

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

Saya lampirkan $(...)tanda kutip di dan yang tampaknya memperbaiki masalah "Tidak ada file atau direktori". Namun, koneksi saya masih dicetak meskipun tty saya ( pts/0) seharusnya dikecualikan:

$ 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)

Pada titik ini, saya sama sekali tidak tahu mengapa grepkueri tidak berfungsi.


4
Bagaimana kalau menggunakan set -xdulu ... Kemudian jalankan perintah Anda dan lihat apa yang sebenarnya Anda cobagrep ...
don_crissti

@don_crissti ah, saya mengerti; itu memberitahu saya bahwa saya sebenarnya grep"tidak sedikit". Bagaimana Anda menyarankan saya mengatasi ini?
menikah

Jawaban:


18

Zachary telah menjelaskan sumber masalahnya.

Meskipun Anda bisa mengatasinya

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

Itu akan salah seperti misalnya jika tty itu pts/1, Anda akhirnya tidak termasuk semua baris yang berisi pts/10. Beberapa grepimplementasi memiliki -wopsi untuk melakukan pencarian kata

who | grep -vw pts/1

tidak akan cocok pts/10karena pts/1di sana tidak diikuti oleh karakter non-kata.

Atau Anda dapat menggunakan awkuntuk memfilter nilai persis bidang kedua seperti:

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

Jika Anda ingin melakukannya dalam satu perintah:

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

Stdin asli diduplikasi ke file descriptor 3 dan dikembalikan untuk ttyperintah.


3
+1 untuk mencari tahu bagaimana melakukannya dalam satu perintah dan menunjukkan kesalahan itu.
Zachary Brady

Satu lagi satu liner:tty | cut -f3-4 -d'/' | xargs -I % sh -c "who | grep -v %"
axxis

20

Dari halaman info tty.

'tty' mencetak nama file terminal yang terhubung ke input standarnya. Mencetak `bukan tty 'jika input standar bukan terminal.

Masalahnya adalah bahwa dalam contoh Anda stdin tty adalah pipa, bukan terminal Anda.

Anda dapat melihat dari contoh ini.

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

Untuk menyiasatinya Anda bisa melakukan sesuatu seperti ini.

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

Ada cara yang lebih cepat / lebih efisien namun membutuhkan dua perintah.

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

@Christopher, apakah Anda satu-satunya yang masuk ke komputer Anda?
Zachary Brady

@ Chrisopher, aneh. Jadi who | grep -v "$(ps ax | grep "^$$" | awk '{ print $2 }')"menghasilkan output yang diharapkan pada kotak saya dan t=$(tty) who|grep -v "${t:5}"tidak menghasilkan apa-apa.
Zachary Brady

Shell / versi apa yang Anda gunakan? GNU bash, version 4.1.2
Zachary Brady

2
ps ax | grep "^ *$$"bisa salah mencocokkan misalnya shell Anda 123 dan 1234 ada; ps ax -otty= $$lebih kuat dan hanya satu proses. Tapi saya lebih suka milik Anda ${t:5}atau Stephane ${t#/dev/}(atau substr(t,6))
dave_thompson_085

1
Tolong jangan tambahkan penafian. Meskipun niatnya terpuji, mereka tidak benar-benar membantu jawabannya. Jika seseorang menunjukkan kesalahan dalam jawaban Anda, cukup edit jawaban Anda untuk memasukkan koreksi.
terdon
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.