왜`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가 아님"을 말하는 것 입니다. 내가이 문제를 어떻게 해결하겠습니까?
아마 maybeharry

답변:


18

Zachary는 문제의 원인을 설명했습니다.

당신이 그것을 해결할 수있는 동안

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

에 단어가 아닌 문자가 pts/10없기 때문에에 일치 pts/1하지 않습니다.

또는 다음 awk과 같이 두 번째 필드의 정확한 값을 필터링 하는 데 사용할 수 있습니다 .

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

하나의 명령으로 수행하려면 다음을 수행하십시오.

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

원래 stdin은 파일 설명자 3에 복제되어 tty명령을 위해 복원됩니다 .


3
한 번의 명령으로 수행하는 방법을 알아 내고 그 실수를 지적한 +1
Zachary Brady

라이너 하나 더 :tty | cut -f3-4 -d'/' | xargs -I % sh -c "who | grep -v %"
axxis

20

tty 정보 페이지에서.

'tty'는 표준 입력에 연결된 터미널의 파일 이름을 인쇄합니다. 표준 입력이 터미널이 아닌 경우 'not tty'를 인쇄합니다.

문제는 예제에서 tty의 stdin이 터미널이 아닌 파이프라는 것입니다.

이 예제에서 볼 수 있습니다.

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

그 문제를 해결하려면 다음과 같이 할 수 있습니다.

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

더 빠르고 효율적인 방법이 있지만 두 가지 명령이 필요합니다.

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

@Christopher 당신은 당신의 컴퓨터에 로그인 한 유일한 사람입니까?
Zachary Brady

@ 크리스토퍼, 이상하다. 따라서 who | grep -v "$(ps ax | grep "^$$" | awk '{ print $2 }')"내 상자에서 예상되는 출력을 t=$(tty) who|grep -v "${t:5}"생성하고 아무것도 생성하지 않습니다.
Zachary Brady

어떤 쉘 / 버전을 사용하고 있습니까? GNU bash, version 4.1.2
Zachary Brady

2
ps ax | grep "^ *$$"셸이 123이고 1234가 존재하는 경우, 일치하지 않을 수 있습니다. ps ax -otty= $$더 강력하고 단 하나의 프로세스입니다. 그러나 나는 당신 ${t:5}이나 Stephane 's ${t#/dev/}(또는 substr(t,6))를 선호합니다
dave_thompson_085

1
면책 조항을 추가하지 마십시오. 의도는 칭찬 할 만하지 만 실제로 답변을 돕는 것은 아닙니다. 누군가가 귀하의 답변에 결함을 지적하면 수정 사항을 포함하도록 답변을 편집하십시오.
terdon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.