트랙
/
AWK
AWK
/
학습 과정
/
기초 개념
기초

기초 개념 에서 AWK

1개의 연습 문제

기초 개념 소개

_언어_는 AWK라고 하고, AWK 프로그램을 해석하는 _실행 파일_은 awk 또는 **gawk**라고 부를게요.

패턴과 액션

AWK 프로그램은 패턴-액션 쌍으로 이루어져 있어요.

pattern1 { action1 }
pattern2 { action2 }
...

패턴은 입력과 대조할 정규 표현식 패턴이 될 수 있어요. 참/거짓 값을 내놓는 어떤 표현식이든 될 수도 있어요.

액션은 하나 이상의 AWK 명령이에요. 감싸는 중괄호는 반드시 필요해요.

패턴의 결과가 _참_이면, 그에 해당하는 액션이 실행돼요.

레코드와 필드

AWK는 입력을 일련의 레코드로 읽어요. 각 레코드는 다시 0개 이상의 필드로 나뉘어요.

기본 동작은 이래요.

  • 줄 바꿈을 "레코드 구분자"로 삼아 입력을 레코드로 나눠요. 그래서 각 _줄_이 하나의 레코드가 돼요.
  • 공백 문자를 "필드 구분자"로 삼아 레코드를 필드로 나눠요. 그래서 각 _단어_가 하나의 필드가 돼요.

패턴과 액션 (계속)

패턴은 생략할 수 있어요. 그러면 액션이 _모든 입력 레코드_에 대해 실행돼요.

액션도 생략할 수 있어요. 그러면 기본 동작으로 현재 레코드를 출력해요.

특수한 패턴

자주 쓰이는 특수한 패턴이 두 가지 있어요.

  • BEGIN은 입력을 하나도 읽기 전에 연결된 액션을 실행해요.
  • END는 모든 입력을 다 읽은 뒤에 연결된 액션을 실행해요.

필드 변수

필드는 $1, $2, $3 등으로 가리켜요.

현재 레코드는 $0이에요.

Caution

분명히 해두자면, 이것들은 엄밀히 말해 "변수"가 아니에요. $는 주어진 필드 번호의 값을 가져오는 _연산자_라고 볼 수 있어요. 이 부분은 이후 개념에서 더 자세히 살펴봐요.

그 밖에 자주 쓰이는 내장 변수도 있어요.

입력 파싱을 제어하는 내장 변수

  • RS는 입력 레코드 구분자예요. 앞에서 말했듯이 기본값은 줄 바꿈이에요.
  • FS는 입력 필드 구분자예요.

이 변수들은 보통 BEGIN 액션 블록에서 설정해요.

정보를 전달하는 내장 변수

이 변수들은 프로그램이 실행되는 동안 AWK가 자동으로 설정해요.

  • NF는 현재 레코드의 필드 개수를 저장해요.
    • 마지막 필드의 값을 얻으려면 $NF를 사용해요.
  • NR은 현재 레코드 번호를 저장해요.
    • 여러 입력 파일을 처리할 때는 NR이 지금까지 처리한 전체 레코드 수를 담아요.
  • FNR은 현재 입력 파일에서의 레코드 번호를 저장해요.
    • NR과 FNR의 차이를 보여 주는, 흔히 쓰이는 AWK 관용구가 있어요.
      NR == FNR {action}
      
      이것은 "누적 레코드 번호가 현재 파일의 레코드 번호와 같으면"이라는 뜻이에요. 이 조건은 _첫 번째 입력 파일_의 레코드에서만 참이 될 수 있어요.

참과 거짓의 판정

AWK는 C와 참과 거짓을 판정하는 개념이 같아요.

  • 숫자 0은 거짓이에요.
  • 다른 모든 숫자는 참이에요.

AWK는 텍스트를 다루는 언어라서, 참/거짓 판정이 문자열에도 확장돼요.

  • 빈 문자열 ""은 거짓이에요.
  • 비어 있지 않은 문자열은 참이에요.
Note

AWK는 C와 참과 거짓을 판정하는 개념이 같아요

AWK는 1970년대에 Bell Labs에서 만들어졌는데, C가 탄생한 것과 같은 환경이었어요. C는 AWK의 문법에 큰 영향을 주었어요.

Caution

주의해야 할 이상한 점이 하나 있어요

  • 숫자 0은 거짓이에요.
  • 비어 있지 않은 문자열 "0"은 참이에요!

AWK의 데이터 타입은 다음 개념들에서 더 다뤄요.

주석

주석은 # 문자로 시작하고 줄 끝까지 이어져요.

awk에 입력을 주는 방법

awk는 파일이나 표준 입력에서 입력을 읽을 수 있어요. 다음 방법이 모두 잘 동작해요.

awk '/regex/ {print $1}' file1 file2 ...

awk '/regex/ {print $1}' < file

some_command_here | awk '/regex/ {print $1}'

예제

유닉스 계열 시스템에서 /etc/passwd에는 사용자 정보가 들어 있어요. 각 사용자는 한 줄씩 따로 설명되고, 필드는 콜론으로 구분돼요.

사용자 이름을 나열하려면 이렇게 해요.

awk '
    BEGIN { FS = ":" }
    { print $1 }
' /etc/passwd

{print $1} 액션에는 패턴이 없어서, 모든 레코드에 대해 실행된다는 점을 눈여겨봐요.

로그인 셸로 bash를 사용하는 사용자만 출력하고 싶다면 이렇게 하면 돼요.

awk '
    BEGIN { FS = ":" }
    $7 == "/bin/bash" { print $1 }
' /etc/passwd

몇 가지 예제 더

다른 흔한 유닉스 명령과 같은 결과를 내는 awk 프로그램도 있어요.

  • 파일 내용 출력하기

    cat file.txt
    
    awk '1' file.txt
    
  • 파일에서 패턴 찾기

    grep 'foo.*bar' file.txt
    
    awk '/foo.*bar/' file.txt
    
  • 파일 앞부분에서 몇 줄만 출력하기

    head -n 20 file.txt
    
    awk '
        1
        NR == 20 {exit}
    ' file.txt
    
  • 파일에서 텍스트 바꾸기

    sed 's/foo/bar/' file.txt
    
    awk '{sub(/foo/, "bar")};1' file.txt
    # or more readably
    awk '
        {
            sub(/foo/, "bar")
            print
        }
    ' file.txt
    
GitHub에서 편집 링크가 새 창이나 탭에서 열려요

기초 개념 배우기