awk의 gensub 또는 대안을 사용하여 겹치는 일치 항목을 바꾸는 방법

awk의 gensub 또는 대안을 사용하여 겹치는 일치 항목을 바꾸는 방법

나는 다음을 사용하고 있습니다 :

$ echo ".a.b.c." | awk '
{
  t=gensub(/.([a-z])./,"[\\1]","g",$1); print t
}'
[a]b[c]

나는 그것을 끝내고 싶다 [a][b][c]. gensub중복 일치 항목 처리를 시작하려면 어떻게 해야 하나요 ?

이것이 가능하지 않다면 어떻게 이를 달성할 수 있습니까?

답변1

다음과 같이 할 수 있습니다:

perl -pe 's{\.([a-z](?:\.[a-z])*)\.}{"[$1]" =~ s/\./][/gr}ge'

즉, 모두를 로 바꾸고 .x.y.z.s 를 [x.y.z].바꿉니다 ][.

또한 awk, gensub()성공 여부를 알려주지 않기 때문에 구체적이고 사용하기 번거로운 gawk 사용을 피하세요.

awk '
  {
    while(match($0, /(\.[abcdefghijklmnopqrstuvwxyz])+\./)) {
      s = substr($0, RSTART + 1, RLENGTH - 2)
      gsub(/\./, "][", s)
      $0 = substr($0, 1, RSTART - 1) "["s"]" substr($0, RSTART+RLENGTH)
    }
    print
  }'

현재 버전 mawk(아직 현지화되지 않음) 또는 최신 버전을 사용하는 경우 gawk또는 C 로케일인 경우 abcdefghijklmnopqrstuvwxyz로 대체될 수 있습니다 a-z. 이러한 조건을 넘어서면 동일하다는 보장은 없습니다. 특히 일부 로케일에서는 [a-z]각 POSIX가 다음 순서와 일치하도록 설계되었습니다.요소 구성, 아니요수치ddzs헝가리어 로케일 처럼 여러 문자를 일치시키는 것도 가능합니다 .

어쨌든 정규식에서 문자 그대로의 포인트를 일치시키려면 \.또는 가 필요합니다 [.]. .그렇지 않으면 그 자체가 단일 문자와 일치하는 정규식 연산자입니다.

답변2

일반적으로 정규식 엔진은 중복되는 일치를 고려하지 않습니다. 이는 제안한 방식이 아니지만 후자의 일치가 이전 대체에 의해 삽입된 문자를 고려하지도 않습니다.

Perl에서는 Lookbehind를 사용하여 닫는 대괄호의 오른쪽을 일치시키고 작업이 수행되는 횟수만큼 (전체 문자열에 대해) 교체를 반복할 수 있습니다. 여기서는 리터럴 포인트 사이의 문자를 일치시키려고 한다고 가정합니다(정규식은 .단일 문자와 일치함).

% cat test.txt
.a.b.c.
..a..
.a.b  c.d.
.a]b.
% perl -pe '1 while s/(\.|(?<=\]))([a-z])\./[$2]/'  < test.txt
[a][b][c]
.[a].
[a]b  c[d]
.a][b]

마지막 행에는 ]다음 일치 항목이 현재 트리거되는 거짓 긍정이 표시됩니다 b.. 먼저 입력에 없을 것 같은 일부 바이트를 삽입한 다음 이를 실제 대괄호로 바꾸면 이를 방지할 수 있습니다. 예를 들어 바이트 값 1, ^A:

% perl -pe '1 while s/(\.|(?<=\001))([a-z])\./[$2\001/; tr/\001/]/' < test.txt
[a][b][c]
.[a].
[a]b  c[d]
.a]b.

제가 발견하지 못한 다른 문제가 있을 수도 있습니다. 대체를 반복할 때 일치가 너무 느슨하면 무한 루프에 빠질 위험이 있지만 대체에는 리터럴 포인트가 필요하고 항상 적어도 하나의 포인트를 제거하므로 위험하지 않아야 합니다.

.( 정규식의 어떤 문자와 일치한다는 의미 라면 예를 abcd들어 가 되어야 할 것 같은데 [b]d, 이상해 보입니다.)

답변3

이것은 루비입니다:

echo ".a.b.c." | ruby -pe '$_.gsub!(/(?:[.][a-z](?=\.))|\./){|m| m[/^\.$/] ? "" : "[#{m[1]}]" }'

또는 펄:

echo ".a.b.c." | perl -pe 's/(?:[.]([a-z])(?=\.))|\./($1 eq "") ? "" : "[$1]" /ge'

또는 다음을 인쇄하세요.

[a][b][c]

관련 정보