"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
서로 관련이 없는 서로 다른 두 언어에 대한 두 명의 통역사입니다.
구문은 awk
C와 매우 유사합니다.
에서는 셸에서와 달리 awk
변수가 참조됩니다 var
. 여기서 in은 입력 필드의 값을 검색하는 단항 연산자입니다(0에 적용하면 전체 레코드가 검색됩니다). 예를 들어, 6번째 필드의 값을 검색합니다. 단항 인지 여부에 관계없이 연산자 해석은 물론이고 in 의 문자열 상수 내부에는 변수 보간이 없습니다 .$var
$
awk
$ (3 + 3)
awk
-
+
$
따라서 in 은 awk
리터럴 "${#5}"
값을 가진 문자열 상수입니다 ${#5}
.
"${#5}" -lt
, 문자열과 변수에 "string" - lt
동일한 이진 연산자가 적용됩니다. 산술 연산자이므로 두 피연산자가 모두 숫자로 변환됩니다. 둘 다 결과 숫자처럼 보이는 것으로 시작하므로 둘 다 0입니다.-
lt
0 - 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
.