Linux에서 텍스트 조작을 위해 AWK 언어 사용하는 방법

소개

리눅스 유틸리티는 종종 Unix 설계 철학을 따릅니다. 도구들은 작고 입력 및 출력으로 평범한 텍스트 파일을 사용하고 모듈식으로 작동하도록 장려됩니다. 이러한 유산으로 인해, 우리는 sedawk와 같은 도구를 사용하여 훌륭한 텍스트 처리 기능을 갖추고 있습니다.

awk는 텍스트 데이터를 매우 유용한 방식으로 조작하는 데 사용할 수 있는 프로그래밍 언어 및 텍스트 프로세서입니다. 이 가이드에서는 awk 명령 줄 도구를 사용하는 방법과 텍스트를 처리하는 방법을 살펴보겠습니다.

기본 구문

awk 명령은 모든 현대 리눅스 시스템에 기본적으로 포함되어 있으므로 사용을 시작하려면 설치할 필요가 없습니다.

awk는 예측 가능한 방식으로 서식이 지정된 텍스트 파일을 처리할 때 가장 유용합니다. 예를 들어, 테이블 형식의 데이터를 구문 분석하고 조작하는 데 우수합니다. 파일을 한 줄씩 처리하며 전체 파일을 반복합니다.

기본적으로 공백(공백, 탭 등)을 필드로 분리합니다. 다행히도 리눅스 시스템의 많은 구성 파일이 이 형식을 사용합니다.

awk 명령어의 기본 형식은 다음과 같습니다:

  1. awk '/search_pattern/ { action_to_take_on_matches; another_action; }' file_to_parse

검색 부분 또는 동작 부분 중 하나를 생략할 수 있습니다. 기본적으로 “동작” 부분이 지정되지 않은 경우 취해지는 동작은 “출력”입니다. 이는 단순히 일치하는 모든 줄을 출력합니다.

검색 부분이 지정되지 않은 경우 awk는 각 줄에 나열된 동작을 수행합니다.

둘 다 지정된 경우 awk는 현재 줄이 패턴을 반영하는지 여부를 결정하기 위해 검색 부분을 사용하고 일치하는 경우 동작을 수행합니다.

가장 간단한 형태에서는 awkcat처럼 사용하여 텍스트 파일의 모든 줄을 화면에 출력할 수 있습니다.

일련의 친구들의 좋아하는 음식을 나열하는 favorite_food.txt 파일을 생성하세요:

  1. echo "carrot sandy
  2. wasabi luke
  3. sandwich brian
  4. salad ryan
  5. spaghetti jessica" > favorite_food.txt

이제 awk 명령어를 사용하여 파일을 화면에 출력하세요:

  1. awk '{print}' favorite_food.txt

파일이 화면에 출력됩니다:

Output
carrot sandy wasabi luke sandwich brian salad ryan spaghetti jessica

이것은 그다지 유용하지 않습니다. 파일에서 텍스트 “sand”를 검색하여 awk의 검색 필터링 기능을 시도해 보겠습니다:

  1. awk '/sand/' favorite_food.txt
Output
carrot sandy sandwich brian

awk는 이제 “sand” 문자를 포함하는 줄만 출력합니다.

정규 표현식을 사용하여 텍스트의 특정 부분을 대상으로 할 수 있습니다. “sand”로 시작하는 줄만 표시하려면 다음 정규 표현식을 사용하십시오: ^sand:

  1. awk '/^sand/' favorite_food.txt

이번에는 한 줄만 표시됩니다:

Output
sandwich brian

마찬가지로, 동작 부분을 사용하여 인쇄할 정보의 일부를 지정할 수 있습니다. 예를 들어, 첫 번째 열만 인쇄하려면 다음 명령어를 사용하십시오:

  1. awk '/^sand/ {print $1;}' favorite_food.txt
Output
sandwich

모든 열을 변수와 연결된 열 번호로 참조할 수 있습니다. 예를 들어, 첫 번째 열은 $1, 두 번째는 $2이며, 전체 줄은 $0으로 참조할 수 있습니다.

내부 변수 및 확장된 형식

awk 명령은 파일을 처리하는 동안 특정 정보를 할당하기 위해 일부 내부 변수를 사용합니다.

awk가 사용하는 내부 변수는 다음과 같습니다:

  • FILENAME: 현재 입력 파일을 참조합니다.
  • FNR: 현재 입력 파일에 대한 현재 레코드 번호를 참조합니다. 예를 들어, 두 개의 입력 파일이 있는 경우 각 파일의 레코드 번호를 총계가 아닌 파일별로 알려줍니다.
  • FS: 레코드의 각 필드를 나타내는 현재 필드 구분자입니다. 기본적으로 공백으로 설정됩니다.
  • NF: 현재 레코드의 필드 수입니다.
  • NR: 현재 레코드의 번호입니다.
  • OFS: 출력된 데이터의 필드 구분자입니다. 기본적으로 공백으로 설정됩니다.
  • ORS: 출력된 데이터의 레코드 구분자입니다. 기본적으로 개행 문자입니다.
  • RS: 입력 파일에서 별도의 레코드를 구별하는 데 사용되는 레코드 구분자입니다. 기본적으로 이는 새 줄 문자입니다.

이러한 변수의 값을 파일의 필요에 맞게 자유롭게 변경할 수 있습니다. 일반적으로 이것은 처리의 초기화 단계 중에 수행됩니다.

이것은 또 다른 중요한 개념으로 이어집니다. awk 구문은 여태까지 사용한 것보다 약간 더 복잡합니다. 선택적으로 BEGINEND 블록도 있으며 각각 파일 처리 전후에 실행할 명령을 포함할 수 있습니다.

이로써 우리의 확장된 구문은 다음과 같이 보입니다:

  1. awk 'BEGIN { action; }
  2. /search/ { action; }
  3. END { action; }' input_file

BEGINEND 키워드는 검색 매개변수와 마찬가지로 특정한 조건 세트입니다. 이들은 문서가 처리된 전후에 일치합니다.

즉, BEGIN 섹션에서 일부 내부 변수를 변경할 수 있습니다. 예를 들어, /etc/passwd 파일은 공백 대신 콜론(:)으로 구분됩니다.

이 파일의 첫 번째 열을 출력하려면 다음 명령을 실행하세요:

  1. awk 'BEGIN { FS=":"; }
  2. { print $1; }' /etc/passwd
Output
root daemon bin sys sync games man . . .

BEGINEND 블록을 사용하여 인쇄 중인 필드에 대한 정보를 인쇄할 수 있습니다. 다음 명령을 사용하여 파일에서 데이터를 테이블로 변환하고 탭으로 아름답게 공간을 만듭니다:

  1. awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; }
  2. {print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}
  3. END { print "---------\nFile Complete" }' /etc/passwd

다음 출력이 표시됩니다:

Output
User UID GID Home Shell -------------- root 0 0 /root /bin/bash daemon 1 1 /usr/sbin /bin/sh bin 2 2 /bin /bin/sh sys 3 3 /dev /bin/sh sync 4 65534 /bin /bin/sync . . . --------- File Complete

보시다시피, awk의 기능을 활용하여 출력을 꽤 멋지게 포맷할 수 있습니다.

확장된 섹션들 중 각각은 선택 사항입니다. 사실, 다른 섹션을 정의한 경우에는 주요 작업 섹션이 선택 사항입니다. 예를 들어, 이렇게 할 수 있습니다:

  1. awk 'BEGIN { print "We can use awk like the echo command"; }'

그리고 이 출력을 볼 수 있습니다:

Output
We can use awk like the echo command

이제 출력의 필드 내에서 텍스트를 찾는 방법을 살펴 보겠습니다.

필드 검색 및 복합 표현식

이전 예제 중 하나에서는 “sand”로 시작하는 favorite_food.txt 파일의 줄을 출력했습니다. 전체 줄의 시작을 찾았기 때문에 이것은 쉬웠습니다.

그런데 만약 검색 패턴이 필드의 시작 부분과 일치하는지 알고 싶다면 어떨까요?

각 사람의 음식 앞에 항목 번호를 추가한 favorite_food.txt 파일의 새 버전을 만듭니다:

  1. echo "1 carrot sandy
  2. 2 wasabi luke
  3. 3 sandwich brian
  4. 4 salad ryan
  5. 5 spaghetti jessica" > favorite_food.txt

이 파일에서 “sa”로 시작하는 모든 음식을 찾으려면 다음과 같은 작업을 시도해 볼 수 있습니다:

  1. awk '/sa/' favorite_food.txt

이렇게 하면 “sa”가 포함된 모든 줄이 표시됩니다:

Output
1 carrot sandy 2 wasabi luke 3 sandwich brian 4 salad ryan

여기서 단어의 어느 부분에서든 “sa”에 일치시킵니다. 이는 “wasabi”와 같은 가운데에 패턴이 있는 것이나 원하지 않는 “sandy”와 같은 것을 포함하게 됩니다. 이 경우에는 두 번째 열에서 “sa”로 시작하는 단어에만 관심이 있습니다. 시작하는 “sa”로만 두 번째 열에 있는 단어입니다.

당신은 이 명령어를 사용하여 awk에게 두 번째 열의 시작 부분에만 일치하도록 지시할 수 있습니다:

  1. awk '$2 ~ /^sa/' favorite_food.txt

이렇게 하면 일치 항목을 찾을 때 두 번째 열의 시작 부분에서만 검색할 수 있습니다.

field_num ~ 부분은 awk가 두 번째 열에만 주의를 기울여야 함을 지정합니다.

Output
3 sandwich brian 4 salad ryan

동일하게 “!” 문자를 물결(~) 문자 앞에 포함하여 일치하지 않는 항목을 쉽게 검색할 수 있습니다. 이 명령은 “sa”로 시작하는 음식이 없는 모든 줄을 반환합니다:

  1. awk '$2 !~ /^sa/' favorite_food.txt
Output
1 carrot sandy 2 wasabi luke 5 spaghetti jessica

“sa”로 시작하지 않고 항목 번호가 5보다 작은 줄에만 관심이 있다고 나중에 결정하면 다음과 같이 복합 표현식을 사용할 수 있습니다:

  1. awk '$2 !~ /^sa/ && $1 < 5' favorite_food.txt

여기에는 몇 가지 새로운 개념이 소개됩니다. 첫 번째는 && 연산자를 사용하여 일치하는 줄에 대한 추가 요구 사항을 추가할 수 있는 능력입니다. 이를 사용하면 줄이 일치하려면 임의의 수의 조건을 결합할 수 있습니다. 이 경우 첫 번째 열의 값이 5보다 작은지를 확인하는 검사를 추가하기 위해 이 연산자를 사용합니다.

다음 출력이 표시됩니다:

Output
1 carrot sandy 2 wasabi luke

awk를 파일 처리에 사용할 수 있지만 다른 프로그램의 출력물도 처리할 수 있습니다.

다른 프로그램의 출력 처리

다른 프로그램의 출력을 지정된 파일 이름을 사용하는 대신 awk 명령을 사용할 수 있습니다. 예를 들어, ip 명령에서 IPv4 주소를 구문 분석하는 데 awk를 사용할 수 있습니다.

ip a 명령은 기계에있는 모든 네트워크 인터페이스에 대한 IP 주소, 브로드캐스트 주소 및 기타 정보를 표시합니다. eth0이라는 인터페이스의 정보를 표시하려면 이 명령을 사용하십시오:

  1. ip a s eth0

다음과 같은 결과가 표시됩니다:

Output
2571: eth0@if2572: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.11/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever

awk를 사용하여 inet 줄을 대상으로하고 IP 주소 만 인쇄 할 수 있습니다:

  1. ip a s eth0 | awk -F '[\/ ]+' '/inet / {print $3}'

-F 플래그는 정규 표현식 [\/ ]+을 사용하여 슬래시 또는 공백으로 분리하도록 awk에 지시합니다. 이렇게하면 라인 inet 172.17.0.11/16이 개별 필드로 분할됩니다. IP 주소는 세 번째 필드에 있습니다. 라인 시작 부분의 공백도 슬래시뿐만 아니라 슬래시로 분리했기 때문에 필드로 계산됩니다.이 경우 awk는 연속적인 공백을 단일 공백으로 취급했습니다.

출력에는 IP 주소가 표시됩니다:

Output
172.17.0.11

awk를 사용하여 다른 명령의 출력을 검색하거나 구문 분석 할 수 있는 여러 위치를 찾을 수 있습니다.

결론

지금쯤이면, 텍스트 파일 및 텍스트 스트림을 조작, 형식화 및 선택적으로 출력하는 방법에 awk 명령을 사용할 수 있는 기본적인 이해가 있어야합니다. 그러나 Awk는 실제로 변수 할당, 제어 구조, 내장 함수 등이 포함된 전체 프로그래밍 언어입니다. 신뢰할 수 있는 방식으로 텍스트를 형식화하기 위해 자신의 스크립트 내에서 사용할 수 있습니다.

awk에 대해 더 알아보려면 그 창조자들에 의한 무료 공용 도메인 도서를 읽어보십시오. 이 책은 훨씬 더 자세히 설명합니다.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-the-awk-language-to-manipulate-text-in-linux