awk if 문에서 별표를 사용하는 방법

awk if 문에서 별표를 사용하는 방법

한 줄을 인쇄해야 하지만 숫자를 검색하려면 awk를 사용하고 더 많은 숫자와 함께 이중 콜론을 추가해야 하는 시나리오가 있습니다.

아래 예를 참조하세요.

test1 test2 37:375003 test3 test4
test1 test2 38:375004 test3 test4
test1 test2 39:375005 test3 test4
test1 test2 40:375006 test3 test4
test1 test2 41:375007 test3 test4

내가 달성하고 싶은 것은 다음과 같은 명령을 사용하는 것입니다.

cat test_out.txt | awk "{if ($3 == 37~/\:*/ ) print $0;}"

위 내용은 다음 줄을 제공합니다.

test1 test2 37:375003 test3 test4

다음 구문 오류가 발생합니다.

Syntax Error The source line is 1.
The error context is
             {if ( >>>  == <<<
awk: 0602-502 The statement cannot be correctly parsed. The source line is 1.

답변1

~구문은 다음과 같은 이항 연산자를 사용해야 합니다 .

string ~ regexp

문자열을 정규식과 일치시키려면 다음을 수행하십시오.

<test_out.txt awk '$3 ~ /^37:[[:digit:]]+$/'

세 번째 필드가 확장 정규식( {print}기본 작업의 약어)과 일치하는 레코드를 인쇄합니다.{print $0}^37:[[:digit:]]+$

ERE 구문에서:

  • ^주제의 시작 부분과 일치
  • [...]: 세트의 모든 문자 또는 조합 요소와 일치합니다.
  • [:digit:]위의 집합은 로케일에서 10진수로 분류된 모든 문자를 나타냅니다(대부분의 시스템에서는 0123456789로 제한됨). 다른 십진수와 일치하지 않으려면 0123456789지원되지 않는 POSIX 문자 클래스로 변경하세요. 또한 작동하지만 일부 구현에서는 다른 문자와 일치할 수도 있습니다.mawk0-9mawkawk
  • +위의 항목 중 하나 이상을 대상으로 합니다. 여기 하나 이상의 숫자가 있습니다
  • $주제의 끝과 일치합니다.

다음 부분이 숫자로 구성되어 있는지 신경 쓰지 않는다면 37:정규 표현식은 ^37:( 37:주제 시작 부분)입니다.

또 다른 방법은 다음과 같습니다.

<test_out.txt awk '$3 + 0 == 37'

+ 0숫자 연산은 초기 숫자 뒤의 모든 항목을 무시하고 숫자로 awk변환을 시도합니다. $3그러면 이는 일치 37:anything하지만 일부 구현 과 일치 할 수 있는 37.0;whatever1, 3.7e+11 도 일치합니다 . 표준을 사용하더라도 일부 구현에서는 작동하지 않습니다 .0x25#xxxawk+37+38+$3 == 37awk

37쉘 변수(여기)에서 오는 값의 경우 쉘에서 정규 표현식을 구성하고 이를 ment 변수를 awk통해 전달할 수 있습니다.ENVIRON

var=37
ERE='^'$var':[[:digit:]]+$' <test_out.txt awk '$3 ~ ENVIRON["ERE"]'

또는 awk v쉘 변수에서 변수²를 생성하십시오.

var=37
<test_out.txt awk -v n="$var" '$3 ~ "^" n ":[[:digit:]]+"'

다음과 같이 셸 변수를 awk코드로 확장하지 마세요.

<test_out.txt awk '$3 ~ /^'"$var"':[[:digit:]]+$/'

이로 인해 종종 명령 주입 취약점(최악의 취약점 유형)이 발생하기 때문입니다.

귀하의 시도에 대한 몇 가지 의견:

  • 이미 똑같아@RudyC가 지적함, awk 코드 주위에 큰따옴표를 사용했습니다. 쉘은 거기에서 매개변수 확장을 수행하므로 $3쉘 스크립트의 세 번째 매개변수 값과 $0스크립트 이름이 확장됩니다.
  • $3 == 37 ~ /\:*/.==다음보다 높은 우선순위~. 그래서 그것은 ($3 == 37) ~ /\:*/. 이는 \:*정규식을 비교 결과와 일치시킵니다( $337인지 여부에 따라 1 또는 0).
  • \:*정규식이 지정되지 않았기 때문에 \:지정되지 않았습니다 . text 와 일치하려면 단독 :입니다 :. :*0 또는 그 이상이 될 것이므로 :문자열에 최소 0 :이 포함되어 있으므로 무엇이든 일치합니다. *정규식에서 0개 이상의 이전 항목과 일치합니다. *이를 0개 이상의 문자와 일치하는 쉘 와일드카드와 혼동 할 수 있습니다 . 정규식에서 0개 이상의 문자는 단일 문자와 일치하는 연산자 .*입니다 ..
  • awk명령문의 형식은 condition {action}다음과 같습니다.상황또는행동생략 가능합니다. 귀하의 경우에는 생략했습니다.상황그리고 if사용행동, {print $0}기본값인 것을 사용합니다.행동. 이것이 작동하는 동안에는 매우 사용자 awk친화적 이지 않을 수 있습니다 awk.
  • 거의 의미가 없는 파일을 cat연결한 적이 있습니다 . cat쉘은 리디렉션을 사용하여 파일 자체를 awk표준 입력으로 열 수 있으므로 프로세스를 절약하고 파이프를 통해 항목을 푸시할 필요가 없습니다. 파일 이름을 매개변수로 전달하면 awk파일이 자동으로 열립니다.

1 적어도 일부 구현(예: POSIX 모드의 GNU)에서는 소수 기수 문자가 로케일에 있고 로케일에는 .없다고 가정합니다.,awkawk

² -v백슬래시는 ENVIRON일반적으로 사용하기에 더 안전하도록 맹글링되어 있습니다.

답변2

"첫 번째 실수는 스크립트에서 큰따옴표를 사용하는 것입니다 awk. 이로 인해 쉘이 $3쉘에 있는 모든 항목으로 확장됩니다(이 경우 빈 문자열일 수 있음). '대신 작은따옴표나 파일을 사용하세요 .

그런 다음 다른 답변에 표시된 대로 작업에 맞는 올바른 정규식을 사용하세요.

관련 정보