줄 길이가 생각보다 길지 않네요

줄 길이가 생각보다 길지 않네요

"test.txt" 파일에 문자열이 있습니다.

207.46.13.136 - - [22/Jan/2019:03:56:21 +0330] "GET /product/30649?model=60398 HTTP/1.1" 200 41198 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" "-"

나는 다음을 실행했다:

grep 'GET /product/*' test.txt | awk -F "/" '{ if ( "${#5}" -lt 6 ) {print $5} } '

$5따라서 길이가 6보다 작은 모든 문자열을 출력해야 합니다 .

my의 길이 $5가 22( 30649?model=60398 HTTP)이므로 출력이 없을 것으로 예상했지만 여전히 문자열을 출력합니다.

편집: 길이가 "30649?model=60398 HTTP"0인 것을 발견했습니다! 나는 더욱 혼란스러워졌습니다.

무슨 일이에요?

답변1

awk여기서 쉘과 구문을 혼동하고 있습니다 .

sh(또는 bash)는 awk서로 관련이 없는 서로 다른 두 언어에 대한 두 명의 통역사입니다.

구문은 awkC와 매우 유사합니다.

에서는 셸에서와 달리 awk변수가 참조됩니다 var. 여기서 in은 입력 필드의 값을 검색하는 단항 연산자입니다(0에 적용하면 전체 레코드가 검색됩니다). 예를 들어, 6번째 필드의 값을 검색합니다. 단항 인지 여부에 관계없이 연산자 해석은 물론이고 in 의 문자열 상수 내부에는 변수 보간이 없습니다 .$var$awk$ (3 + 3)awk-+$

따라서 in 은 awk리터럴 "${#5}"값을 가진 문자열 상수입니다 ${#5}.

"${#5}" -lt, 문자열과 변수에 "string" - lt동일한 이진 연산자가 적용됩니다. 산술 연산자이므로 두 피연산자가 모두 숫자로 변환됩니다. 둘 다 결과 숫자처럼 보이는 것으로 시작하므로 둘 다 0입니다.-lt0 - 0

그런 다음 (보이지 않는) 연결 연산자를 사용하십시오. x y, x및 에서는 y문자열로 변환되고 연결되어 새 문자열을 생성합니다. 이것은 문자열 의 결과 "${#5}" -lt 6입니다 .("${#5}" - lt) 6"06"

$ gawk 'BEGIN{result = "${#5}" -lt 6; print typeof(result) ": " result}'
string: 06

if이는 true가 0이 아닌 숫자 또는 비어 있지 않은 문자열이 되는 조건 으로 사용되므로 여기서는 항상 다음과 같은 결과를 얻습니다.진짜"06"비어 있지 않은 문자열이기 때문입니다 .

올바른 awk구문은 다음과 같습니다.

awk -F "/" '{ if (length($5) < 6) print $5 }'

아니면 좀 더 표준화된 방법을 사용하세요.<condition> {<action>}무늬:

awk -F/ 'length($5) < 6 {print $5}'

또한 grep 'GET /product/*'검색 GET /product뒤에는 임의 개수의 문자(0 포함)가 따르 /므로 기능적으로 와 동일합니다 grep 'GET /product'. 또한 일반적 awk으로 grep함께 파이프할 필요가 없습니다. 그래서 여기 있습니다:

awk -F/ 'index($0, "GET /product/") && length($5) < 6 {print $5}'

index($0, "string")string전체 레코드에서 ( )를 찾는 것은 $0와 같습니다 grep -F 'GET /product/'. /regexp/(의 약어 $0 ~ /regexp/) 도 참조하십시오 grep -E regexp.

관련 정보