예상치 못한 해리 행동

예상치 못한 해리 행동

여기에서 Awk의 분할 동작에 대해 읽었습니다.

[...] 이것FS논쟁나뉘다함수(문자열 함수 참조)는 확장 정규식으로 해석되어야 합니다. 이것들은 다음과 같습니다.오히려~토큰 또는 임의의 표현식이며 or 연산자의 오른쪽과 동일한 방식으로 해석되어야 합니다 !~.

그리고:

오른쪽 피연산자가 어휘 토큰이 아닌 표현식인 경우 오히려, 표현식의 문자열 값은 위의 이스케이프 규칙을 포함하여 확장된 정규 표현식으로 해석됩니다.

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html#tag_20_06_13_04

그러나 다음 코드에서 예상치 못한 결과가 나타났습니다.

BEGIN {
  print split("te.st", q, ".")
}

나는 .어떤 문자라도 표현되고 그 결과가 가 되기를 원합니다 6. 그러나 내 모든 테스트가 반환됩니다 2. 이 코드를 실행하면 예상되는 결과가 나타납니다 6.

BEGIN {
  print split("te.st", q, /./)
}

시험용:

  • 멍하니
  • 멍청한 - POSIX
  • 모크 1.3.4
  • 모크 1.3.3
  • nawk (원래 awk)

제가 문서를 잘못 이해한 건가요, 아니면 버그인가요?

답변1

이것은 실수가 아닙니다. 단지 기존 관행을 성문화하려고 할 때 표준이 충분히 명확하지 않다는 것입니다.

mawk(1) 매뉴얼이 더 명확합니다:

split(expr, A, sep)작동 방식은 다음과 같습니다.

...

(2) sep = " "(단일 공백)이면 은 앞뒤 <SPACE>에서 잘려 가 됩니다 expr. mawk는 정규식으로 정의됩니다 . 그렇지 않으면 정규식으로 처리됩니다.sep<SPACE><SPACE>/[ \t\n]+/sep단, 길이가 1인 문자열의 경우 메타문자가 무시됩니다., 예를 들어 split(x, A, "*")split(x, A, /*/)는 동일합니다.

또한 GNU awk 매뉴얼은 다음에서 나옵니다.현재 소스:

split(s, a [, r [, seps] ])

...

분할은 위에서 설명한 필드 분할과 동일하게 작동합니다. 특히 r단일 문자 문자열인 경우 해당 문자열은 정규식 메타 문자인 경우에도 구분 기호 역할을 합니다.

susv4에 대한 설명입니다.기준:

확장 정규 표현식은 표현식이 포함된 문자열을 내장 변수에 할당하여 필드를 구분하는 데 사용할 수 있습니다.FS, 직접적으로 또는 이 옵션을 사용한 결과로 발생합니다 -F sepstring. 기본값FS변수는 단일 <space>여야 합니다. 아래에서 소개해보자FS행동:

  1. 만약에FS빈 문자열이며 동작이 지정되지 않았습니다.
  2. 만약에FS단일 문자:

    ㅏ. 만약에FS<space>의 경우 선행 및 후행 <blank> 및 <newline> 문자는 건너뜁니다. 필드는 하나 이상의 <blank> 또는 <newline> 문자 집합으로 구분되어야 합니다.

    b. 그렇지 않은 경우FS다른 문자 c는 무엇입니까?필드는 c가 발생할 때마다 구분되어야 합니다..

  3. 그렇지 않으면 문자열 값FS확장된 정규식으로 처리되어야 합니다. 확장된 정규 표현식과 일치하는 시퀀스가 ​​나타날 때마다 필드가 구분됩니다.

귀하의 예는 2.b와 일치합니다.

명시적으로 언급되었음에도 불구하고 이는 인수가 공백인 경우를 포함하여 FS세 번째 인수를 제외한 모든 awk 구현에 사용되는 인수와 동일하게 작동합니다 .split

FS변수는 단지 문자열이기 때문에 동작이 변경될 가능성이 없습니다 ( or awk와 같은 정규식 개체가 없습니다 . or 와 같은 변수에 정규식을 할당할 수 없습니다 ). 이는 위와 같은 작업을 수행하는 함수(암시적으로 또는 명시적으로 호출됨) 입니다. 매개변수를 해석하는 방법입니다.javascriptperla=/./$a=qr/./split

이 동작의 원인은 "오래된" awk와의 호환성 때문일 수 있습니다. 여기서 FS( or 의 세 번째 인수 split)는 항상 단일 문자로 처리되었습니다. 예(UNIX v7):

$ awk 'BEGIN{FS="."; print split("foo.bar.baz", a, "bar"); print a[2] }'
3
ar.
$ awk 'BEGIN{FS="."; print split("foo.bar.baz", a, /bar/); print a[2] }'
awk: syntax error near line 1
awk: illegal statement near line 1
Bus error - core dumped

관련 정보