이 "grep -v"가 예상대로 작동하지 않는 이유는 무엇입니까?

이 "grep -v"가 예상대로 작동하지 않는 이유는 무엇입니까?

query 와 관련된 이상한 문제가 있습니다 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지금까지 쿼리가 실패한 이유를 전혀 모릅니다 .

답변1

tty 정보 페이지에서.

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

문제는 귀하의 경우 tty의 표준 입력이 터미널이 아니라 파이프라는 것입니다.

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

$ 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}"

답변2

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

원래 표준 입력은 파일 설명자 3에 복사되고 tty명령에 대해 복원됩니다.

관련 정보