awk를 스트림 편집기로 사용

awk를 스트림 편집기로 사용

awk텍스트 조작의 스위스 군용 칼입니다. 다만, 본문의 작은 부분을 변경해야 할 경우에는 sed전체적인 수정을 가하겠습니다. 아마도 작업에 가장 적합한 도구일 수 있지만 이러한 간단한 작업을 수행하기 위해 다른 도구를 사용하는 방법을 아는 것도 가치가 있습니다. awk흐름 편집기를 대체 하여 어떻게 사용합니까 sed?

특히 다음 파일을 사용하십시오 text.

Comparing apples with oranges.
Comparing rockets with bicycles.

다음 결과를 얻는 방법 awk:

sed 's/apples/fruit/' text
sed 's/apples\|oranges/fruit/g' text

awk보너스로, 이 함수를 사용하여 변수를 어떻게 변경할 수 있나요?

답변1

스트림 편집기는 특별한 유형의 필터입니다. 필터는 표준 입력에서 텍스트를 가져와서 몇 가지 마법을 수행하고 이를 표준 출력으로 인쇄하는 프로그램입니다. grep, 기본적으로 모든 coreutils필터. 스트림 편집기는 특별한 유형의 필터입니다. 들어오는 텍스트에 하나 이상의 편집 명령을 적용합니다.

에서는 awk다음 세 가지 기능을 사용할 수 있습니다.아들,격자, 그리고뿌리요약은 다음과 같습니다.

sub(regexp, replacement [, target])
gsub(regexp, replacement [, target])
gensub(regexp, replacement, how [, target])

세 가지 함수 모두 target생략 하면 $0현재 행( )이 가정됩니다.

서브와 gsub

먼저 살펴 보겠습니다 sub.

$ awk '{rt = sub(/apple|orange/, "fruit"); print rt, $0}' text 
1 Comparing fruits with oranges.
0 Comparing rockets with bicycles.

여기서 함수의 반환값은 sub()에 저장됩니다 rt. /apple|orange/일치 apple또는 orange적용을 의미하는 정규 표현식한 번. 호출 후에는 아무 일도 일어나지 않지만 sub, 그 뒤에서는 현재 행이 변경되고 반환 값에 값이 있습니다.

반환값은 0아무런 변화가 없는 값입니다. 즉, sub 를 외부에 적용하면 {action}시뮬레이션에 사용할 수 있다는 의미입니다 sed.

$ awk 'sub(/apple|orange/, "fruit")' text    
Comparing fruits with oranges.

이제 첫 번째 줄만 변경되었으므로 첫 번째 줄만 인쇄됩니다. 지정하지 않으면 해당 행을 인쇄하는 작업이 수행된다는 점을 기억하십시오.

시뮬레이션하려면 sed 's/apple/fruit/' text다음과 같이 작성할 수 있습니다.

$ awk 'sub(/apple|orange/, "fruit") || 1' text
Comparing fruits with oranges.
Comparing rockets with bicycles.

이제 첫 번째 기능이 시도됩니다. 무언가가 교체된 경우 0이 아닌 값이 반환되고 해당 줄이 인쇄됩니다. 아무것도 대체되지 않으면 PATTERN두 번째 테스트가 시도됩니다. 이는 항상 0이 아닙니다. 즉, 1. 결과적으로 (수정되지 않은) 줄이 인쇄됩니다.

동일하고 아마도 더 관용적으로 작성하는 또 다른 방법은 다음과 같습니다.

$ awk '{sub(/apple|orange/, "fruit")};1' text 
Comparing fruits with oranges.
Comparing rockets with bicycles.

여기에서는 첫 번째 블록 ACTION의 현재 행을 변경해 봅니다. 반환 코드는 sub자동으로 무시됩니다. 아무것도 인쇄되지 않습니다. 두 번째 PATTERN{ACTION}- 블록( 1), 항상성냥, idf top의 기본 작업은 수정된 줄인지 수정되지 않은 줄인지에 관계없이 인쇄하는 것입니다.

첫 번째 줄의 두 번째 항목은 대체되지 않은 것을 확인했습니다 orange. 한 가지 해결책은 sub-function을 while 루프로 래핑하는 것입니다.

$ awk '{while (sub(/apple|orange/, "fruit")){}};1' text
Comparing fruits with fruits.
Comparing rockets with bicycles.

sub는 0이 아닌 값이 반환되는 한 sub반복됩니다 . 이를 편리하게 단축하고 while 루프가 a에서 작동하지 않기 때문에 PATTERN함수가 도입되었습니다.gsub

$ awk 'gsub(/apple|orange/, "fruit")' text             
Comparing fruits with fruits.

이것은 sed 's/regex/replacement/g'유명한 것들이 다음과 같이 모방될 수 있다는 것을 의미합니다:awk

awk '{gsub(/apple|orange/, "fruit")};1' text

gensub: 부작용 없음

경고하다: gensubPOSIX awk 표준을 준수하지 않으며 설치 시 사용하지 못할 수도 있습니다. gawk에서는 사용할 수 있지만 에서는 busybox awk사용할 mawk수 없습니다 nawk.

이러한 메커니즘은 이미 변수 작업이 작동하는 방식 중 일부를 보여줍니다. 변수가 그 자리에서 변경됩니다.

$ awk '{a=$0; rt=sub(/apple|orange/, "fruit", a); print rt, a, $0}' text
1 Comparing fruits with oranges. Comparing apples with oranges.
0 Comparing rockets with bicycles. Comparing rockets with bicycles.

이것은 당신이 원하는 것이 아닐 수도 있습니다. 컴퓨팅의 건전한 원칙은 입력 자체를 처리하는 것이 아니라 입력의 복사본을 처리하는 것입니다. 입력을 변경하고 싶지 않지만 대체 결과를 새 변수에 할당하면 어떻게 되나요? 입력하다 gensub.

$ awk '{rt=gensub(/apple|orange/, "fruit", "g"); print rt, $0}' text
Comparing fruits with fruits. Comparing apples with oranges.
Comparing rockets with bicycles. Comparing rockets with bicycles.

여기서 반환값은 반환값이 아니지만, 결과 문자열이 변수 rt에 할당됩니다. 이제 네 번째 매개변수의 기본값은 $0입니다.

gensub에 대한 세 번째 인수는 방법입니다. 이 매개변수의 적절한 값은 "g" 또는 "G"이며 이는 전역을 나타냅니다. 그러면 /regex/의 모든 항목이 대체 문자열로 변경됩니다. i번째 항목이 대체되는 양의 정수 i를 지정할 수도 있습니다.

$ gawk '{print gensub(/apple|orange/, "fruit", 1)}' text
Comparing fruits with oranges.
Comparing rockets with bicycles.

$ gawk '{print gensub(/apple|orange/, "fruit", 2)}' text
Comparing apples with fruits.
Comparing rockets with bicycles.

$ gawk '{print gensub(/apple|orange/, "fruit", 3)}' text
Comparing apples with oranges.
Comparing rockets with bicycles.

$ gawk '{print gensub(/apple|orange/, "fruit", "g")}' text
Comparing fruits with fruits.
Comparing rockets with bicycles.

gawk는 양의 정수나 G 또는 g로 시작하는 문자열이 아닌 경우 경고를 발행합니다.

gensub의 또 다른 관용적 사용법은 대체 결과를 직접 인쇄하는 것입니다. 마지막 형식은 sed 's/regex/replacement/g'명령을 대체할 수도 있습니다.

교체용 스트링으로 더 많은 작업 수행

지금까지 우리는 직접 문자열 교체를 수행했습니다. 일치하는 문자열을 수정하려면 어떻게 해야 합니까?

일치하는 텍스트를 캡처하는 특수 변수가 있습니다. POSIX 준수 sub 및 gsub를 사용하면 &를 사용하여 일치하는 부분을 반복할 수 있습니다.

$ awk '{rt=gsub(/apple|orange/, "a basket of &"); print rt, $0}' text
2 Comparing a basket of apples with a basket of oranges.
0 Comparing rockets with bicycles.

sed와 perl/PCRE에서 숫자 일치와 관련된 이상한 점은 sub 및 gsub 변형에 비해 너무 현대적입니다. gensub는 &와 동일한 작업을 수행할 수 있지만 정규식을 지정하기 위해 정규식에서 그룹화를 사용하면 더 많은 작업을 수행할 수 있습니다.

$ awk '{rt=gensub(/(appl|orang)(e)/, "a basket of \\1\\2","g"); print rt}' text
Comparing a basket of apples with a basket of oranges.
Comparing rockets with bicycles.

TL;DR

빠르고 더러운 작업에는 sub 및 gsub를 사용하십시오.

  • 변수를 즉시 변경하고 싶고 이전 값에 신경 쓰지 않는 경우
  • 반환 코드를 사용하여 교체 여부에 따라 작업을 수행하려는 경우

gensub다른 모든 경우에는 다음을 사용하십시오.

  • 대체 문자열에 더 자세한 역참조를 제공합니다.
  • 원래 변수를 변경하지 않고 유지하려는 경우
  • 결과를 변수에 할당하려는 경우

관련 정보