정규식 패턴의 경우 && 논리 연산자가 awk에서 작동하지 않습니다.

정규식 패턴의 경우 && 논리 연산자가 awk에서 작동하지 않습니다.

조금 이상해 보이는 것은 &&의 논리 연산자가 ||의 논리 연산자와 달리 awk if 정규식 패턴에서 작동하지 않는다는 것입니다. 효과가있다!
참고: 하지만 && 논리 연산자는 순수하고 단순한 awk 정규식 모드에서 작동하는데, 그 이유는 무엇일까요?

# 
# 
# cat /etc/passwd|awk '$0 ~/[Ss]ystem/ || /puls/ {print $0}'
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
# 
# 
# 
# cat /etc/passwd|awk '$0 ~/[Ss]ystem/ &&  /puls/ {print $0}'
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
# 
# 
# 
# cat /etc/passwd|awk '$0 ~/[Ss]ystem|puls/ {print $0}'
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
# 
# 
# 
# cat /etc/passwd|awk '{k1[NR]=$0}END{for(i=1;i<=NR;i++)if(k1[i] ~/[Ss]ystem/ || /puls/){print k1[i]}}'
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
# 
# 
# cat /etc/passwd|awk '{k1[NR]=$0}END{for(i=1;i<=NR;i++)if(k1[i] ~/[Ss]ystem/ && /puls/){print k1[i]}}'
# 
# 
# cat /etc/passwd|awk '{k1[NR]=$0}END{for(i=1;i<=NR;i++)if(k1[i] ~/[Ss]ystem/ && /puls/){print k1[i]}}'
# 
# 
# cat /etc/passwd|awk '$0 ~/[Ss]ystem/ &&  /puls/ {print $0}'
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
# 
# 


이제 약간의 변화를 주었으니 최근 상황이 이전보다 더 이상해질 수도 있습니다!
배열 변수와 논리 연산자 &&가 있는 아래의 동일한 정규식 패턴이 작동하는 이유는 무엇입니까?
참고: 정규식 패턴이 적어도 배열 변수 자체와 관련이 없는 경우 && 문제 중 일부를 설명해야 합니다.
# 
# 
# cat /etc/passwd|awk '{k0[NR]=$0;if(k0[NR] ~/[Ss]ystem/ && /puls/){print k0[NR]}}'
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
# 
# 
# cat /etc/passwd|awk '{k0[NR]=$0;if(k0[NR] ~/[Ss]ystem/ || /puls/){print k0[NR]}}'
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
# 
# 
# cat /etc/passwd|awk '{k0[NR]=$0;if(k0[NR] ~/[Ss]ystem/ && /puls/){print k0[NR]}}'
pulse:x:497:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
# 
# 

답변1

첫 번째 부분에서는

$0 ~/[Ss]ystem/ &&  /puls/

암시적이다

$0 ~/[Ss]ystem/ && $0 ~ /puls/

그래서

if(k1[i] ~/[Ss]ystem/ && /puls/)

다음과 같이 작성해야 합니다.

if(k1[i] ~/[Ss]ystem/ && k1[i] ~ /puls/)
  • 전자의 경우 (*)가 의 마지막 줄과 일치할 가능성/pusl/ 이 높습니다 ./etc/passwd
  • 또한 참조하십시오. man awk그러나 ~(및 !~)이 우선합니다.&&

(*) 확인, PulseAudio 라인을 마지막 라인으로 이동하면 매칭이 완료됩니다.

답변2

잘못된 연산자 연결과 그 의미를 가정하고 있습니다. 테스트 케이스에 번호를 매깁니다.

  1. $0 ~/[Ss]ystem/"$0이 /RE/"와 일치하는지 확인하세요. 조건은 || /puls/테스트조차 되지 않습니다. 전체 조건이 참인 것으로 알려져 있으므로 "단락"된 것입니다.

  2. &&두 조건이 모두 true이고 하나의 행만 일치하는지 확인합니다 .

  3. 결합된 RE(두 가지 대안 포함 |)는 두 행과 일치합니다.

  4. 이는 포함된 스토리지 라인과 일치합니다 System.

  5. 이건 아무것도 일치하지 않습니다. 배열에 저장된 행을 테스트하지만 "/puls/"는 $0의 값을 테스트합니다.뒤쪽에파일 끝 부분을 실행했습니다. k1[i]를 참조하지 않습니다. $0에는 여전히 파일의 마지막 줄이 포함됩니다. 전체 입력 파일의 끝에는 그러한 줄이 없다고 가정합니다. 두 조건이 모두 충족 &&되어야 하므로 일치하는 행이 없습니다.

  6. (5)의 반복이다.

  7. (2)의 반복입니다.

답변3

다음은 원래 질문의 "최신" 버전을 단순화하여 분해한 것입니다.

cat /etc/passwd|awk '{k0[NR]=$0;if(k0[NR] ~/[Ss]ystem/ && /puls/){print k0[NR]}}'

awk 자체가 파일을 읽을 수 있기 때문에 cat은 코드에 아무것도 추가하지 않습니다. (자세한 내용은 Google UUOC를 참조하세요.)

입력 행을 배열에 저장한 다음 동일한 명령문에서 값을 테스트하면 아무 것도 추가되지 않습니다(END 블록이 없기 때문). 따라서 다음과 같이 단순화할 수 있습니다.

awk '{if($0 ~/[Ss]ystem/ && /puls/){print $0}}' /etc/passwd

패턴 일치를 사용하는 ~것은 일반 RE와 동일하므로 다음과 같이 단순화됩니다.

awk '{if(/[Ss]ystem/ && /puls/){print $0}}' /etc/passwd

an을 사용하는 것은 if중괄호 밖의 패턴과 동일하므로 다음과 같습니다.

awk '/[Ss]ystem/ && /puls/ {print $0}' /etc/passwd

print $0print와 동일하며 { print }작업이 기본 작업이므로 다음과 같습니다.

awk '/[Ss]ystem/ && /puls/' /etc/passwd

귀하의 초기 주장 " &&작동하지 않지만 ||잘 작동합니다"가 잘못되었습니다.

이것은 "패턴 A의 경우그리고패턴 B가 이 입력 라인에 나타납니다.":

awk '/[Ss]ystem/ && /puls/' /etc/passwd

이것은 "패턴 A의 경우또는패턴 B가 이 입력 라인에 나타납니다.":

awk '/[Ss]ystem/ || /puls/' /etc/passwd

관련 정보