728x90
텍스트 처리를 위한 유틸리티는 대표적으로 sed(stream editor)와 awk가 있음
1. AWK
- awk
데이터를 조작하고 리포트를 생성하기 위해 사용하는
언어 리눅스에서 사용하는 awk는 GNU 버전의 gawk로 심볼릭 링크되어 있음 - 간단한 연산자를 명령라인에서 사용할 수 있으며, 큰 프로그램을 위해 사용 가능
awk는 데이터를 조작할 수 있기 때문에 쉘 스크립트에서 사용되는 필수 툴이며,
작은 데이터베이스를 관리하기 위해서도 필수 - Alfred Aho, Peter Weinberger, Brian Kernighan 3명의 제작자 이름 이니셜을 가져와서 awk
1.1 awk 프로그래밍 형식
- awk 를 입력하고, 작은따옴표로 둘러싸인 패턴이나 액션을 입력,
마지막에 입력 파일 이름 파일 이름을 지정하지 않으면 키보드 입력에 의한 표준 입력을 받음 - awk는 입력된 라인들의 데이터들을 공백 또는 탭을 기준으로 분리,
$1부터 시작하는 각각의 필드 변수로 분리하여 인식
! AWK 형식
- awk 'pattern' filename
- awk '{action}' filename
- awk 'pattern {action}' filename
- 예시
$ vi awkfile 홍 길동 3324 5/11/96 50354 임 꺽정 5246 15/9/66 287650 이 성계 7654 6/20/58 60000 정 약용 8683 9/40/48 365000 $ awk '{print $0}' awkfile > 홍 길동 3324 5/11/96 50354 임 꺽정 5246 15/9/66 287650 이 성계 7654 6/20/58 60000 정 약용 8683 9/40/48 365000 $ awk '{print $1}' awkfile > 홍 임 이 정 $ awk '/길동/' awkfile > 홍 길동 3324 5/11/96 50354 $ awk '/정/{print "\\t안녕하세요? " $1, $2 "님!"}' awkfile > 안녕하세요? 임 꺽정님! 안녕하세요? 정 약용님! $ awk '/홍/{print $1, $3}' awkfile > 홍 3324 $ df | awk '$4 < 100000' : |을 이용해 파이프라인 생성 > devfs 368 368 0 100% 638 0 100% /dev map -hosts 0 0 0 100% 0 0 100% /net map auto_home 0 0 0 100% 0 0 100% /home |
! AWK 동작 원리
- awk는 파일 또는 파이프를 통해 입력 라인을 얻어와
$0라는 내부 변수에 라인을 입력 각 라인은 레코드라고 부르고, newline에 의해 구분 - 라인은 공백을 기준으로 각각의 필드나 단어로 나뉨 필드는 $1부터 시작. 많게는 100개 이상의 필드 저장 가능
- 내장 변수인 FS라고 부르는 필드 분리자가 공백을 할당받음
필드가 콜론/대시와 같은 문자에 의해 분리되면 새로운 필드 분리자로 FS의 값 변경 가능 - awk는 화면에 필드를 출력할 때 print 함수를 사용
- 콤마는 출력필즈 분리자(OFS)와 매핑되어 있으며 공백을 할당받음
! OFMT 변수
- 숫자를 출력할 때 숫자 포맷 제어할 경우 사용. 간단히 printf를 사용할 수도 있지만, OFMT를 지정할 수 있음.
- default는 %.6g로 소수점 6자리
$ awk 'BEGIN{OFMT="%.2f"; print 1.23412, 15E-3}' > 1.23 0.01 |
! printf 함수
- 포매팅된 깔끔한 출력을 할 경우 사용
- newline을 제공하지 않기 때문에 newline이 요구되면 \\n을 사용해야함
- c : 문자, d : 10진수, f : 실수, x : 16진수
- ``이 붙으면 좌측에서 시작되고 기본형이면 우측에서 시작
$ awk '{printf "The name is %-20s Number is %4d\\n", $1" "$2, $3}' awkfile > The name is 홍 길동 Number is 3324 The name is 임 꺽정 Number is 5246 The name is 이 성계 Number is 7654 The name is 정 약용 Number is 8683 |
! awk -f 옵션
- awk 액션과 명령이 파일에 작성되어 있다면 f 옵션을 사용
awk -f [awk 명령파일] [awk 명령을 적용할 텍스트 파일]
$ vi awkcommand {print "안녕하세요 " $1, $2"님"} {print $1, $2, $3, $4, $5} $ awk -f awkcommand awkfile > 안녕하세요 홍 길동님 홍 길동 3324 5/11/96 50354 안녕하세요 임 꺽정님 임 꺽정 5246 15/9/66 287650 안녕하세요 이 성계님 이 성계 7654 6/20/58 60000 안녕하세요 정 약용님 정 약용 8683 9/40/48 365000 |
! 레코드와 필드
- 레코드- awk는 입력 데이터를 볼 수 없지만 포맷 또는 구조는 볼 수 있음. 각 라인(레코드)은 newline으로 분리
- NR 변수 : 각 레코드들의 번호는 awk의 빌트인 변수 NR에 저장/ 레코드가 저장된 다음 NR의 값은 하나씩 증가
$ awk '{print NR, $0}' awkfile > 1 홍 길동 3324 5/11/96 50354 2 임 꺽정 5246 15/9/66 287650 3 이 성계 7654 6/20/58 60000 4 정 약용 8683 9/40/48 365000 |
- 필드
- 빌트인 변수 FS는 입력 필드 분리자의 값을 가지고 있음
- Default는 공백과 탭/ FS값 변경을 위해서는 F를 사용, F 다음 오는 문자가 새로운 필드 분리자
$ vi awkfile_FS 홍 길동 :3324 :5/11/96 :50354 임 꺽정 :5246 :15/9/66 :283502 $ awk -F: '/홍/{print $1, $2}' awkfile_FS > 홍 길동 3324 $ awk -F'[ :\t]' '/홍/{print $1, $2}' awkfile_FS > 홍 길동 |
! awk와 정규표현식
- 정규표현식은 슬래시로 둘러싸인 문자들로 구성된 패턴
$ awk '/^정/{print $1, $2, $3}' awkfile > 정 약용 8683 $ awk '/^[A-Z][a-z]+ /' awkfile2 > Hong KilgDong 3324 5/11/96 50354 |
- match 연산자(~) : 표현식과 매칭되는 것이 있는지 검사하는 연산자
$ awk '$2 !~ /g$/' awkfile2 : 2번 필드가 g로 끝나지 않는 라인 출력 > Lee Seongkye 7654 6/20/58 60000 |
- POSIX 문자 클래스
$ awk '/[[:lower:]]+g[[:space:]]+[[:digit:]]' awkfile2 > Hong KilgDong 3324 5/11/96 50354 |
! 비교 표현식
- 어떤 상태가 참일때만 액션이 수행
$ awk '$3 > 7000{print $1, $2}' awkfile > 이 성계 정 약용 |
- 조건 표현식
- 표현식을 검사하기 위해 ?와 :를 사용. if/else가 하는 역할과 같은 결과를 의미
$ awk '{max={$1 > $2) ? $1 : $2; print max}' filename if $1 > $2: max = $1 else: max = $2 |
- 산술 연산자
- 계산을 통해 필터링 가능
- 논리연산자
- && : AND 연산
- || : OR 연산
- ! : NOT 연산
$ awk '$3 > $5 && $3 <= 100' filename |
1.2 awk 변수
- BEGIN 패턴
- awk가 입력 파일의 라인들을 처리하기 이전에 실행되며 액션 블록 앞에 놓임
- 입력 파일 없이 테스트할 수 있고, 빌트인 내장 변수(OFS, RS, FS)들의 값을 변경할 경우 사용 - END 패턴
- 어떤 입력 라인과도 매칭되지 않고, 입력 모든 라인이 처리된 후 실행됨
- BEGIN만 사용할 경우, 아규먼트 파일명을 적지 않아도 되지만
END 블록을 사용할 경우엔 반드시 아규먼트 파일을 적어야 함
$ awk '/Tom/{count++}END{print "Tom was found " count " times."}' awkfile5 |
- awk 리다이렉션
- awk결과를 리눅스 파일로 리다이렉션할 경우 쉘 리다이렉션 연산자를 사용
- 파일명은 큰따옴표로 둘러쌰아 함
- > 심볼이 사용될 때 파일이 오픈되고 잘려짐
$ awk -F: '$4 >= 60000 {print $1, $2 > "new_file"}' awkfile5 |
- getline 함수
- 표준 입력, 파이프, 현재 처리되고 있는 파일로부터 입력을 읽기 위해 사용
입력의 다음 라인을 가져와 NF, NR, FNR 빌트인 변수를 설정
- 레코드가 검색되면 1을 리턴하고, 파일의 끝이면 0을 리턴. 에러가 발생하면 -1을 리턴
$ awk 'BEGIN{ "date " | getline d; split(d, year) ; print year[6]}' > 2009 $ awk 'BEGIN{while (getline < "/etc/passwd" > 0)lc++; print lc}' filename |
- awk 파이프
- awk 프로그램에서 파이프를 오픈하고 다른 파이프를 오픈하기 전에 기존 파이프는 닫기
- 파이프 심볼의 오른쪽 명령은 큰따옴표(““)로 둘러싸야 한다
$ awk '{print $1, $2 | "sort-r"}' cars |
- END블록에 close를 사용해 파이프를 꼭 닫아줘야 함
$ awk '{print $1, $2 | "sort -r"} END{close("sort -r")}' cars |
2. SED
- 정규 표현식을 사용하고, 기본 입출력은 표준 입력과 출력을 사용
- 파이프를 통해 한쪽의 출력을 다른 쪽으로 넘길 수 있음
- 주어진 주소 범위에 대해 입력의 어떤 줄을 처리할 것인지 결정
- 주소 범위에는 라인 번호 또는 패턴을 사용 가능
ex) 5d라고 하면 다섯 번째 라인을 삭제 windows/d는 “windows”를 포함하는 모든 라인을 삭제
2.1 sed 동작 원리
- sed 스트림 에디터는 한번에 하나의 파일/ 하나의 입력으로부터 한 라인만 처리, 모니터로 출력
- vi 에디터에서 사용 가능하며, 저장된 라인은 패턴 공간이라고 부르는 임시 버퍼에서 처리
- 임시 버퍼에 있는 라인의 처리가 한번 끝나면 임시 버퍼에 있는 라인은 모니터로 출력
- 라인이 처리된 다음 임시 버퍼에서 라인은 제거, 다음 라인이 임시 버퍼로 읽혀지고 처리/출력
- 예제
- 입력의 8번째 줄을 삭제
- 빈 줄을 모두 삭제
- 첫 줄부터 처음 나타내는 빈 줄까지 삭제
- “Jones”를 포함하는 줄만 출력 (-n 옵션 사용)
- “GUI”가 나오는 줄에서 GUI를 ‘‘로 변경(삭제)
- 8d
728x90
'IT_Engineer > DevOps_Unix & Linux (Bash)' 카테고리의 다른 글
[Linux] 리눅스 환경 정보 확인 총정리 (0) | 2021.03.22 |
---|---|
[Linux] TAR 압축 묶기/풀기 (0) | 2021.01.18 |
[Linux] 정규 표현식 (0) | 2020.12.07 |
[OS] CentOS 7 부팅 USB 만들기 (1) | 2020.12.02 |
[Linux] 리눅스의 부팅 과정과 로그인 쉘 #2 (0) | 2020.11.20 |