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.