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.