Bu grep -v neden beklendiği gibi çalışmıyor?


12

grep -vSorgularla ilgili garip bir sorunum var . Açıklamama izin ver:

Kullandığım bağlantıları görüntülemek için 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)

ttyTerminalimin akımıpts/0

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

Kullanarak kendi bağlantımı dışlamaya çalışıyorum grep -v $(tty | cut -f3-4 -d'/'). Bu komutun beklenen çıktısı, whobağlantım olmadan olmalıdır . Ancak, çıktı en beklenmedik:

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

Ben $(...)tırnak içine alın ve bu "Böyle bir dosya veya dizin yok" sorunu gidermek gibi görünüyor. Ancak, tty ( pts/0) yöntemim hariç tutulsa bile bağlantım hala yazdırılıyor :

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

Bu noktadan itibaren, grepsorgunun neden hatalı çalıştığına dair hiçbir fikrim yok .


4
set -xİlk kullanmaya ne dersiniz ... Sonra komutunuzu çalıştırın ve aslında ne yapmaya çalıştığınızı görün grep...
— don_crissti

@don_crissti ah, anlıyorum; bana aslında grep"tty değil" diyorum . Bunun üstesinden gelmemi nasıl önerirsiniz?
— Mayıs

Yanıtlar:


18

Zachary sorunun kaynağını açıkladı.

Etrafında çalışabilirken

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

Örneğin, bu tty ise pts/1, içeren tüm satırları hariç tutarsınız pts/10. Bazı grepuygulamalarda -wkelime araması yapma seçeneği vardır

who | grep -vw pts/1

eşleştirmesi olmaz pts/10çünkü pts/1orada olmayan bir kelime karakteri tarafından takip edilmez.

Veya aşağıdaki awkgibi ikinci alanın tam değerine filtre uygulamak için kullanabilirsiniz :

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

Bunu tek bir komutta yapmak istiyorsanız:

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

Orijinal stdin, dosya tanımlayıcısına 3 kopyalanır ve ttykomut için geri yüklenir .


3
Tek bir komutta nasıl yapılacağını ve bu hatayı işaret ettiği için +1.
— Zachary Brady

Bir tane daha astar:tty | cut -f3-4 -d'/' | xargs -I % sh -c "who | grep -v %"
— axxis

20

Tty bilgi sayfasından.

'tty', standart girişine bağlı terminalin dosya adını yazdırır. Standart giriş terminal değilse `` tty '' yazdırmaz.

Sorun, örneğinizde tty'nin stdin'inin bir boru olması, terminaliniz değil.

Bu örnekten görebilirsiniz.

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

Bunu çözmek için böyle bir şey yapabilirsiniz.

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

Daha hızlı / daha verimli bir yol var, ancak iki komut gerektiriyor.

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

@Christopher, bilgisayarınıza giriş yapan tek kişi siz misiniz?
— Zachary Brady

@Christopher, tuhaf. Böylece who | grep -v "$(ps ax | grep "^$$" | awk '{ print $2 }')"kutumda beklenen çıktıyı t=$(tty) who|grep -v "${t:5}"üretir ve hiçbir şey üretmez.
— Zachary Brady

Hangi kabuğu / sürümü kullanıyorsunuz? GNU bash, version 4.1.2
— Zachary Brady

2
ps ax | grep "^ *$$"yanlış eşleşme olabilir mesela kabuğunuz 123 ve 1234; ps ax -otty= $$daha sağlam ve sadece tek bir işlemdir. Ama senin ${t:5}ya da Stephane'nin ${t#/dev/}(ya da substr(t,6)) tercih ediyorum
— dave_thompson_085

1
Lütfen feragatname eklemeyin. Niyet övgüye değer olsa da, cevaba gerçekten yardım etmiyorlar. Birisi cevabınızdaki bir kusura dikkat çekerse, düzeltmeyi dahil etmek için cevabınızı düzenleyin.
— terdon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.