awk의 레코드, 필드 및 사용자 지정 구분자
입력 및 출력 필드 구분자를 제어하여 CSV, TSV 및 로그 행을 깔끔한 열로 나누는 방법을 익힙니다.
awk의 레코드, 필드 및 사용자 지정 구분자은(는) CoddyKit의 무료 Linux Command Line & Bash Scripting Mastery 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Linux Command Line & Bash Scripting Mastery 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Linux Command Line & Bash Scripting Mastery 강의에는 총 4개의 강의가 포함되어 있습니다.
awk에서 레코드와 필드란 무엇인가요
awk는 입력을 한 줄씩 읽습니다. 각 줄을 레코드라고 하며, 그 줄 안에서 공백으로 구분된 각 부분을 필드라고 합니다.
$0— 현재 레코드 전체(전체 줄)$1— 첫 번째 필드$2— 두 번째 필드$NF— 마지막 필드(NF= 필드 수)
기본적으로 awk는 연속된 공백이나 탭을 기준으로 필드를 나눕니다. 따라서 로그 분석, 명령 출력, 공백으로 구분된 데이터를 즉시 처리할 수 있습니다.
#!/usr/bin/env bash
# Show how awk sees records and fields
echo 'alice 30 engineer' | awk '{ print "Name:", $1, "Age:", $2, "Role:", $3 }'
# $NF is always the last field — regardless of how many there are
echo 'one two three four five' | awk '{ print "Last field:", $NF }'입력 필드 구분자: FS
내장 변수 FS(필드 구분자)는 awk에 각 레코드를 필드로 나누는 방법을 알려 줍니다. 기본값은 단일 공백이며, 공백 기준 분할 모드를 활성화합니다.
FS는 다음 두 가지 방법으로 설정할 수 있습니다.
- 명령줄에서
-F플래그 사용:awk -F':' BEGIN블록 안에서 설정:BEGIN { FS = ":" }
두 방법은 동일합니다. 긴 스크립트에서는 구성 설정을 스크립트 자체에 넣어 가독성과 이식성을 높일 수 있으므로 BEGIN 블록 방식을 선호합니다.
#!/usr/bin/env bash
# Parse /etc/passwd using ':' as the field separator
# Field 1 = username, field 3 = UID, field 7 = shell
echo 'root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin' \
| awk -F':' '{ print $1, "UID="$3, "shell="$7 }'BEGIN 블록에서 FS 설정하기
한 줄짜리 명령보다 긴 스크립트에서는 BEGIN 블록 안에 FS를 배치하는 것이 표준적인 방법입니다. BEGIN 블록은 awk가 입력을 읽기 전에 실행되므로 첫 번째 레코드부터 구분자가 준비되어 있습니다.
이 패턴을 사용하면 여러 변수를 한 번에 설정하고 주석을 추가하며 로직을 스크립트 파일 안에 자체적으로 정리할 수도 있습니다.
실무에서 자주 만나는 구분자는 다음과 같습니다.
- 콜론
:—/etc/passwd,/etc/shadow - 탭
\t— TSV 내보내기, 컴파일러 출력 - 쉼표
,— CSV 파일(인용된 필드 없음) - 파이프
|— 일부 로그 형식, 데이터베이스 덤프
#!/usr/bin/env bash
# awk script using BEGIN to set FS for TSV input
printf 'alice\t30\tengineer\nbob\t25\tdesigner\ncarol\t35\tmanager\n' \
| awk 'BEGIN { FS = "\t" } { printf "%-10s age=%-3s role=%s\n", $1, $2, $3 }'awk로 CSV 파일 분석하기
CSV(쉼표로 구분된 값)는 셸 엔지니어링에서 가장 흔한 데이터 형식 중 하나입니다. FS=","로 설정하면 awk가 쉼표를 구분자로 사용합니다.
중요한 주의 사항: awk에 내장된 CSV 처리는 쉼표를 포함한 인용 필드를 처리하지 못합니다(예: "Smith, John"). 인용된 쉼표가 없는 단순한 CSV에서는 완벽하게 작동합니다. 인용 필드가 있는 RFC 4180 준수 CSV에는 적절한 CSV 분석기나 miller/csvkit을 사용하십시오.
실무에서 흔한 작업은 특정 열을 추출하고 값으로 행을 필터링하는 것입니다. FS만 설정하면 awk로 두 작업을 쉽게 수행할 수 있습니다.
#!/usr/bin/env bash
# Simple CSV: extract name and salary columns, filter salary > 50000
data='name,department,salary
alice,engineering,95000
bob,marketing,48000
carol,engineering,112000
dave,hr,45000'
echo "$data" | awk -F',' '
NR == 1 { next } # skip header row
$3 > 50000 { print $1, "earns", $3 }
'여러 문자 및 정규식 필드 구분자
awk의 FS는 단일 문자로 제한되지 않으며 정규식일 수도 있습니다. 이는 필드가 길이가 일정하지 않은 구분자로 나뉘는 실제 로그 형식을 처리할 때 강력합니다.
정규식 구분자의 예는 다음과 같습니다.
FS = "[,;]"— 쉼표 또는 세미콜론을 기준으로 나눕니다.FS = "[ \t]+"— 하나 이상의 공백 또는 탭을 기준으로 나눕니다(기본 동작과 같지만 명시적으로 작성한 형태).FS = "::"— 리터럴 이중 콜론을 기준으로 나눕니다.FS = "\\|"— 파이프 문자를 기준으로 나눕니다(이스케이프해야 함).
FS가 정규식이면 awk(gawk)는 이를 리터럴 문자열이 아니라 패턴으로 처리합니다.
#!/usr/bin/env bash
# Log lines with mixed delimiters: split on " | " or "::" or ","
# Here we split on one or more spaces or pipe characters
printf '2024-01-15 | ERROR | disk full | /dev/sda1\n2024-01-15 | INFO | startup ok | main\n' \
| awk -F' \\| ' '{ printf "date=%-12s level=%-6s msg=%s\n", $1, $2, $3 }'
# Split on multiple possible delimiters using character class
echo 'alpha,beta;gamma,delta;epsilon' \
| awk -F'[,;]' '{ for(i=1; i<=NF; i++) print i": "$i }'출력 필드 구분자: OFS
OFS(출력 필드 구분자)는 print로 레코드를 다시 구성할 때 awk가 필드 사이에 넣는 내용을 제어합니다. 기본값은 단일 공백입니다.
핵심은 다음과 같습니다. OFS는 print에서 쉼표 구문을 사용할 때, 또는 필드에 값을 할당하여 awk가 $0을 다시 만들 때만 필드 사이에 삽입됩니다. 소스 코드에서 공백과 함께 연결하면 OFS는 사용되지 않습니다.
print $1, $2, $3— 쉼표가 필드 사이에 OFS를 삽입하게 합니다.print $1 " " $2— 명시적 공백이므로 OFS는 무시됩니다.
일반적인 패턴은 FS=","와 OFS="\t"를 설정하여 CSV를 읽고 변환한 뒤 TSV로 작성하는 것입니다.
#!/usr/bin/env bash
# Convert CSV to TSV using FS and OFS
data='alice,30,engineer
bob,25,designer
carol,35,manager'
echo "$data" | awk 'BEGIN { FS=","; OFS="\t" } { print $1, $2, $3 }'
echo '---'
# OFS also applies when you modify a field — awk rebuilds $0 with OFS
echo 'alice,30,engineer' | awk 'BEGIN { FS=","; OFS=" | " } { $1=$1; print $0 }'OFS로 awk가 $0을 다시 만들도록 하기
미묘하지만 중요한 방법이 있습니다. 어떤 필드에든 값을 할당하면(필드에 자기 자신을 할당하는 $1=$1도 포함) awk가 모든 필드를 OFS로 연결하여 $0을 다시 만들도록 할 수 있습니다.
이는 모든 필드를 직접 출력하지 않고 레코드의 구분자를 다시 형식화하는 관용적인 방법입니다.
FS를 입력 구분자로 설정합니다.OFS를 원하는 출력 구분자로 설정합니다.$1=$1로 다시 만들기를 실행합니다.$0을 출력합니다.
이 방법은 필드 수와 관계없이 확장할 수 있으며 $1, $2, $3, ...을 하드 코딩하지 않아도 됩니다.
#!/usr/bin/env bash
# Reformat a pipe-delimited file to comma-separated WITHOUT listing every field
printf 'alice|30|engineer|london\nbob|25|designer|paris\ncarol|35|manager|berlin\n' \
| awk 'BEGIN { FS="|"; OFS="," } { $1=$1; print $0 }'
# Useful when you don't know how many fields there are:
printf 'a|b|c|d|e|f|g\n1|2|3|4|5|6|7\n' \
| awk 'BEGIN { FS="|"; OFS="\t" } { $1=$1; print $0 }'레코드 구분자: RS
FS가 레코드 내에서 필드를 나누는 것처럼, RS(레코드 구분자)는 레코드와 레코드를 구분하는 기준을 정의합니다. 기본적으로 RS는 newline이므로 awk는 한 번에 한 줄씩 처리합니다.
RS를 변경하면 여러 줄로 구성된 레코드를 강력하게 처리할 수 있습니다.
RS=""— 문단 모드: 빈 줄이 레코드를 구분합니다(필드가 여러 줄에 걸쳐 있을 수 있음).RS=";"— 세미콜론으로 나눕니다(SQL 덤프에 유용함).RS="\n"— 명시적인 줄바꿈입니다(기본값).
문단 모드(RS="")에서도 여러 줄로 된 레코드 안의 필드를 나눌 때 FS가 사용되며, 레코드 내부의 줄바꿈도 자동으로 필드 구분자로 처리됩니다.
#!/usr/bin/env bash
# Paragraph mode: each blank-line-separated block is one record
# Useful for processing structured text blocks (e.g., stanzas, config sections)
data='Name: Alice
Role: Engineer
City: London
Name: Bob
Role: Designer
City: Paris'
echo "$data" | awk 'BEGIN { RS=""; FS="\n" } {
print "Record", NR":"
for (i=1; i<=NF; i++) print " ", $i
print ""
}'출력 레코드 구분자: ORS
ORS(출력 레코드 구분자)는 각 print 문 뒤에 출력됩니다. 기본값은 줄바꿈(\n)이므로 모든 print 출력이 새 줄에 표시됩니다.
ORS를 변경하면 다음과 같은 작업을 할 수 있습니다.
- 레코드를 한 줄로 이어 붙이기:
ORS=" " - 출력 레코드 사이에 빈 줄 추가하기:
ORS="\n\n" - JSON이나 XML 조각과 같은 사용자 지정 출력 형식 만들기
printf는 ORS를 사용하지 않는다는 점에 유의하십시오. ORS는 아무 옵션 없이 사용하는 print 문에만 적용됩니다. 서식을 완전히 제어해야 할 때는 printf를 사용하십시오.
#!/usr/bin/env bash
# Join all matching lines onto one line by setting ORS to a space
printf 'apple\nbanana\ncherry\ndate\n' | awk '{ ORS=" " } { print $0 }'
echo # final newline
# Add a blank line after every output record for readability
printf 'alice 30 engineer\nbob 25 designer\ncarol 35 manager\n' \
| awk 'BEGIN { ORS="\n\n" } { print $1, "is a", $3 }'실전 예제: Apache 액세스 로그 구문 분석
Apache/nginx 액세스 로그는 공백으로 구분된 필드로 이루어진 잘 알려진 형식을 사용합니다. 일부 필드(예: 타임스탬프)에는 공백이 포함되어 대괄호나 따옴표로 묶이므로, awk의 필드 직접 분할이 까다로울 수 있습니다.
실용적인 방법은 구조를 고려하는 정규식 FS를 사용하거나, 정확한 형식을 알고 위치를 기준으로 특정 필드를 추출하는 것입니다.
통합 로그 형식의 필드는 대략 다음과 같습니다.
- 클라이언트 IP
- 식별자(대개
-) - 인증 사용자(대개
-) - 타임스탬프(대괄호 안에 있으며 하나의 토큰으로 계산됨)
- 요청 메서드+경로+프로토콜(따옴표 안에 있음)
- HTTP 상태 코드
- 응답 바이트 수
#!/usr/bin/env bash
# Parse a simulated Apache Combined Log Format line
# Extract: IP, status code, bytes, and request path
logs='192.168.1.10 - alice [15/Jan/2024:10:23:45 +0000] "GET /api/users HTTP/1.1" 200 1523
10.0.0.5 - - [15/Jan/2024:10:23:46 +0000] "POST /login HTTP/1.1" 401 89
172.16.0.3 - bob [15/Jan/2024:10:23:47 +0000] "GET /dashboard HTTP/1.1" 200 8741'
echo "$logs" | awk '{
ip = $1
status = $9
bytes = $10
# Extract the request path from the quoted string in field 7
split($7, parts, "/")
path = "/" parts[2]
printf "ip=%-15s status=%s bytes=%-6s endpoint=%s\n", ip, status, bytes, path
}'파이프라인에서 FS, OFS, RS, ORS 결합하기
실제 셸 작업에서는 이러한 구분자를 따로 사용하는 경우가 드뭅니다. 흔히 사용하는 파이프라인 패턴은 awk를 파이프라인 중간의 형식 변환기로 사용하여 하나의 구조화된 형식을 다른 형식으로 변환하는 것입니다.
구분자를 함께 사용할 때 기억할 핵심 사항은 다음과 같습니다.
- 형식을 변환할 때는
BEGIN에서 항상FS와OFS를 함께 설정하십시오. - 모든 필드를 나열하지 않고 다시 서식 지정하려면
$1=$1을 사용하여$0을 다시 구성하십시오. - 레코드가 실제로 여러 줄에 걸쳐 있을 때만
RS를 변경하십시오. - 출력 레코드 사이의 간격을 제어하려면
ORS를 사용하십시오. - 정밀한 서식 지정에는
printf를 우선 사용하고,ORS의 자동 종료가 편리할 때는print를 사용하십시오.
#!/usr/bin/env bash
# Full pipeline: read a colon-delimited file,
# filter rows where field 3 (UID) >= 1000 (real users),
# then output as tab-separated: username, UID, home dir
echo 'root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
alice:x:1001:1001:Alice:/home/alice:/bin/bash
bob:x:1002:1002:Bob:/home/bob:/bin/zsh
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin' \
| awk 'BEGIN { FS=":"; OFS="\t" } $3 >= 1000 { print $1, $3, $6 }'지식 확인: OFS와 필드 다시 구성
awk에서 필드 할당과 OFS가 어떻게 상호 작용하는지 이해했는지 확인해 보십시오.
단원 요약: 레코드, 필드, 구분자
이제 awk가 구조화된 데이터를 읽고 쓰는 방식을 완전히 제어할 수 있습니다. 네 가지 구분자 변수는 다음과 같습니다.
FS— 입력 필드 구분자입니다.-F또는BEGIN에서 설정합니다. 문자, 문자열 또는 정규식이 될 수 있습니다. 기본값: 공백.OFS— 출력 필드 구분자입니다.print $1, $2호출에서 필드 사이에 삽입되며, 필드 할당 후 awk가$0을 다시 구성할 때도 사용됩니다. 기본값: 단일 공백.RS— 입력 레코드 구분자입니다. 레코드(줄)를 구분하는 기준을 정의합니다. 기본값: 줄바꿈. 문단 모드로 사용하려면 빈 문자열로 설정합니다.ORS— 출력 레코드 구분자입니다. 모든print뒤에 추가됩니다. 기본값: 줄바꿈. 줄을 이어 붙이거나 간격을 추가하도록 변경할 수 있습니다.
가장 중요하게 기억할 패턴은 다음과 같습니다. BEGIN에서 FS와 OFS를 모두 설정한 다음, 필드 위치를 일일이 지정하지 않고 모든 필드의 구분자를 다시 서식 지정하려는 경우 $1=$1을 사용하여 $0을 다시 구성합니다. 이 패턴은 열 개수와 관계없이 모든 파일에서 작동하며, awk 기반 형식 변환 파이프라인의 기반이 됩니다.
자주 묻는 질문
“awk의 레코드, 필드 및 사용자 지정 구분자” 강의는 무료인가요?
네 — “awk의 레코드, 필드 및 사용자 지정 구분자” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Linux Command Line & Bash Scripting Mastery 강의 전체를 잠금 해제할 수 있습니다. Linux Command Line & Bash Scripting Mastery 강의에는 총 4개의 강의가 포함되어 있습니다.
“awk의 레코드, 필드 및 사용자 지정 구분자”에서 뭘 배우나요?
입력 및 출력 필드 구분자를 제어하여 CSV, TSV 및 로그 행을 깔끔한 열로 나누는 방법을 익힙니다. 브라우저에서 직접 실행하는 실습 코드로 Linux Command Line & Bash Scripting Mastery을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Linux Command Line & Bash Scripting Mastery을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Linux Command Line & Bash Scripting Mastery은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“awk의 레코드, 필드 및 사용자 지정 구분자” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Linux Command Line & Bash Scripting Mastery 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Linux Command Line & Bash Scripting Mastery 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- awk의 레코드, 필드 및 사용자 지정 구분자
- 패턴, 범위 및 BEGIN/END 블록
- awk 배열과 그룹화를 활용한 집계
- awk 함수, printf 서식 지정 및 보고서 생성