[RHEL6] 파일 조작 명령어 1탄(a2p, awk, cmp, col, colcrt)
본문 바로가기
IT 이야기/Linux 명령어

[RHEL6] 파일 조작 명령어 1탄(a2p, awk, cmp, col, colcrt)

by 찬찬이 아빠 2020. 3. 31.
반응형
  1. a2p(awk-perl 변환)

 1) 경로 : /usr/bin/a2p

 2) 요약 : awk 스크립트를 perl 스크립트로 변경

 3) 사용 방법 : a2p [옵션] 파일명

 4) 옵션

 -F<문자> : 구분자를 정의. awk의 필드를 나누는 기준이 되는 구분자 변수인 FS 변수를 지정된 문자로 정의

 -o : awk 형식의 스크립트를 변환

 

 5) 추가 설명

awk 스크립트를 perl 스크립트로 변환하는 명령어입니다. awk 명령어에서 예제로 만든 work.awk 스크립트를 가져와 변환해 봅니다. 이 예제는 문서의 단어 개수를 체크하는 스크립트 입니다. wordcount.txt 문서의 단어 개수를 확인해 봅시다.

# awk -F word.awk wordcount.txt
Word Count : 580

 

a2p 명령어를 이용하여 awk 스크립트를 perl 스크립트로 변환합니다.

# a2p wrd.awk
#!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
	if $running_under_some_shell;
    		# this emulates #1 processing on NIH machines.
            # (remove #! line above if indigestible)
            
eval '$'.$1.'$2;' while $ARGV[0] = ~/^([A-Za-z_0-9]+=)(.*)/ && shift;
			# process any FOO=bar switches
            
$[ = 1;		# set array base to 1
$, = ' ';	# set output field separator
$\ = "\n";	# set output record separator

$word = 0;
while (<>) {
	chomp;		# strip record separator
    @Fld = split(' ', $_, -1);
    $word += $#Fld;
}

print 'Word Count: ' . $word;
($End);

 

a2p는 awk 스크립트를 perl 스크립트로 변환하여 화면에 출력합니다. 이 표준 출력을 word.perl 이라는 perl 스크립트 파일로 만들어 실행하면 같은 결과를 얻을 수 있습니다.

# a2p word.awk > worl.perl
#perl word.perl wordcount.txt
Word Count : 580

 

 

 

  2. awk(패턴 처리 언어)

 1) 경로 : /bin/awk

 2) 요약 : 원본 문서에서 패턴을 검사해 원하는 값을 얻음

 3) 사용 방법 : awk [옵션] -F 'script' [변수=값] [파일]

                       awk [옵션] -f 스크립트 파일 [변수=값] [파일]

 4) 옵션

 스크립트 파일 : awk 스크립트로 작성된 파일

 변수 : awk 내의 변수를 지정

 파일 : 대상 파일

 -F : 구분자를 나타냄. -F로 구분자를 지정하지 않을 경우에는 공백을 구분자로 사용

 -f : 스크립트 파일을 이용할 경우 사용

 

 5) 추가 설명

표준 입력으로 값을 받아 awk 스크립트를 통해 원하는 표준 출력을 내보낼 수 있습니다. awk는 1977년 AT&T 연구소의 Alfred V. Aho, Peter J. Weinverger, Brian W. Kernighan 세 사람이 만들었습니다. awk라는 이름도 세 사람 이름의 앞 글자를 가져와서 지었습니다. 이 후 1986년 Paul Rubin과 Jay Fenlason이 GNU 버전의 awk를 만들어서 리눅스에서 사용했습니다.

 

awk는 일정한 규칙을 가지고 있는 데이터를 처리하여 계산, 통계, 비교 분석, 필터링을 통한 데이터 추출 등에 다양하게 사용될 수 있습니다. sed와 비슷한 기능을 한다고 할 수 있으며 awk와 sed의 장점을 묶어서 perl로 발전시켰지만 데이터 구조가 단순할 때는 awk가 더 효과적이어서 지금도 많이 사용하고 있습니다.

 

awk는 단순히 명령어로 사용되거나, 스크립트 내에서 sed와 함께 이용될 수 있고 awk만의 스크립트 파일을 작성할 수도 있습니다. 현재 디렉터리에 있는 파일 목록을 보기 위해 ls -al 명열을 사용합니다.

# ls -al
total 8
drwxr-xr-x	2	chan	chan	4096	Mar 31 16:40	Desktop
-rw-r--r--	1	chan	chan	15		Mar 31 16:43	chan_test

 

ls -al 명령을 사용해서 현재 디렉터리에 있는 파일 목록을 본 다음에 awk를 사용하여 이 목록 중 파일 권한과 파일명만 출력할 수 있습니다. ls -al 명령으로 출력되는 데이터를 파이프(|)로 awk가 받아서 파일의 공백을 기준으로 나누어 첫 번째 필드와 아홉 번째 필드만 출력합니다.

# ls -al
total 8
drwxr-xr-x	2	chan	chan	4096	Mar 31 16:40	Desktop
-rw-r--r--	1	chan	chan	15		Mar 31 16:43	chan_test

# ls -al | awk '{print $1, $9}'
total
drwxr-xr-x	Desktop
-rw-r--r--	chan_test

 

위와 같이 awk는 라인을 받아서 구분자를 통해 구분하고, print 명령으로 출력하게 됩니다. ls -al로 출력되는 행을 공백으로 구분하면 아래오 ㅏ같이 $1~$9 까지 필드로 나뉩니다. 각 필드는 공백을 기준으로 아래처럼 번호로 구분됩니다. $0은 모든 필드를말합니다.

-rw------ 2 root root 23376 Mar 31 16:46 mbox
파일권한 하드링크번호 사용자 그룹 용량 시간 파일명
$1 $2 $3 $4 $5 $6 $7 $8 $9

 

파일 목록 중 1MB가 넘는 파일의 파일명과 용량을 출력하고 싶다면 awk의 조건문을 사용하면 됩니다. 용량을 나타내는 다섯 번째 필드값이 1,048,576(1MB) 보다 큰 숫자를 갖고 있는 라인의 다섯 번째와 아홉 번째 필드만 출력합니다.

# ls -al | awk '$5 > 1048576{print $5, $9}'
5782608	libqt-mt.so.2.3
5761541	libqt.so.2.3.2
1698368	memory_info

 

이 처럼 검색하여 특정 라인과 필드만 출력할 수 있습니다. awk를 이용하면 문서의 특정 문자나 문자열을 검색하여 그 부분만 출력할 수 있습니다. 예를 들어 다음과 같이 하면 /etc/group 파일에서 root를 포함한 라인만 출력합니다.

# awk /root/ /etc//group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
... 중간 생략 ...
adm:x:4:root,adm,daemon
disk:x:6:root
wheel:x:10:root

 

위 출력 결과에서 ":"을 구분자로 하여 분리한 필드 중 첫 번째 필드만 출력하는 awk 명령어를 만들어 봅니다. 첫 번째 필드는 그룹명이고 -F 옵션을 사용해서 ":"를 구분자로 지정합니다.

# awk -F: /root/'{print $1}' /etc/group
root
bin
daemon
sys
adm
disk
wheel

 

/root/ 로 검색한 패턴 부분에 정규 표현식을 사용하면 더욱 자세한 패턴을 검색할 수 있습니다.

 

<스크립트 파일 이용>

awk의 스크립트 구조는 시작, 실행, 마무리의 3단계로 나누어져 있습니다. awk는 연산자나 루프 사용법 등이 C 언어와 같아 C언어를 알고 있는 사용자라면 쉽게 사용할 수 있습니다.

시작(Begin) 시작 단계로서 전체 스크립트를 위한 정의 단계(Preprocessor)
실행(Routin) 실행 단계로 이 스크립트의 기능을 수행하는 단계
끝(End) 마무리 단계로 결과를 출력

 

word.awk라는 이름으로 파일 내에 단어의 개수를 알아보는 awk 스크립트를 만들어 봅니다. 사실 단어 개수를 셀 때는 wc 명령어를 사용하면 쉽습니다.

#!/bin/awk
BEGIN {
wrod = 0;
}
{ word += NF;}
END { print "Word Count: " word;(End)}

 

awk 스크립트의 구조를 분석하면 아래와 같이 나눌 수 있습니다.

awk 스크립트 구조 실행
#!/bin/awk 선언 awk로 스크립트가 실행될 수 있게 선언

BEGIN {

word = 0;

}

시작 변수 wrd를 0으로 초기화

{ word += NF;}

실행

NF는 각 라인 마다의 필드 수를 나타내는 awk 시스템 변수.

구분자 정의가 없으면 공백을 구분자로 사용하므로 각 라인의 단어 수가 NF로 들어가고 "+=" 연산자에 의해서 마지막 라인의 단어 수 까지 더해줌

END { print "Word Count: " word;(End)}

마무리 단계. 결과를 출력

 

작성된 스크립트는 -f 옵션으로 실행합니다. wordcount.txt 라는 임의의 텍스트 문서를 방금 지정한 스크립트로 검사해 봅니다. 작성된 awk 스크립트 파일은 awk -f [스크립트 파일] [대상 파일]로 실행합니다.

# awk -f word.awk wordcount.txt
Word Count : 580

 

<awk 시스템 변수>

변수 내용
$0 입력 라인 모두
$n 입력 라인에서 n번째 필드 값
ARGC 명령 라인 인자 수를 갖는 변수
ARGV 명령 라인 인자 수를 갖는 변수
ENVIRON 환경 변수들을 모아둔 관계형 배열
FILENAME 현재 파일명
FS 구분자 정의. 공백을 기본으로 사용
FNR 입력 파일의 레코드 총수(라인 수)
NF 현재 레코드 필드 수
NR 현재 레코드 번호
OFMT 숫자에 대한 출력 포맷
OFS 출력 필드 구분. 빈 라인을 기본으로 사용
ORS 출력 레코드 부분 (newline을 기본으로 사용)
RLENGTH 지정한 패턴으로 검색되어 나온 문자열의 길이
RS 입력 레코드 구분(newline을 기본으로 사용)
RSTART 지정한 패턴으로 검색되어 나온 문자열의 가장 앞부분

 

<awk 연산자>

C 언어를 참조하여 만들어 졌으므로 C 언어와 사용법이나 종류가 거의 같습니다.

연산자 설명
?

조건연산 사용자로 등록된 아이디가 user1, user2, user3으로 되어 있고 그 중 검색하고 싶은 내용이 1/2/3 중 어떤 것일지 명확하지 않을 경우 ?를 이용하여 모두 검색할 수 있습니다.

 

# awk/user?/etc/passwd

user1:x:516:516::/home/user1:/bin/bash

user2:x:517:517::/home/user2:/bin/bash

user3:x:518:518::/home/user3:/bin/bash

||, $$, !

논리 연산자. or, and, not

~,!~

검색된 패턴에 부합되는 것을 참으로 사용하려면 "~", 거짓으로 사용하려면 "!~"을 사용

<. <=, >=, !=, ==

비교 연산자

+, -, *, /, %, ^

더하기, 빼기, 곱학, 나누기, 나머지, 제곱

++, --

증가 연산자. 감소 연산자

 

 

 

  3. cmp(파일 비교)

 1) 경로 : /usr/bin/cmp

 2) 요약 : 파일을 비교하여 다른 부분을 알려 줌

 3) 사용 방법 : cmp [옵션]

 4) 옵션

 -l(엘) : 각 차이점에 대한 바이트 넘버와 다른 바이트 값을 출력

 -s : 아무런 메시지를 출력하지 않음. 단지 종료 상태만 남김(0 : 차이 없음, 1 : 차이점 있음)

 

 5) 추가 설명

cmp 명령어는 diff 명령어의 간단한 버전이라고 할 수 있습니다. diff가 두 파일 간의 차이점을 상세하게 보여 주는 반면, cmp는 차이점이 있고 없고 만을 확인할 수 있습니다.

 

cmp를 이요한 파일 비교를 위해 간단한 텍스트 파일을 만들어 봅니다. echo 명령을 이용하여 간단한 텍스트가 삽입된 파일을 만들어 봅니다.

# echo "hello world" > cmo_test
# echo "hello world friend" > cmp_test2

 

두 파일을 cmp 명령으로 비교합니다. 첫 번째 줄의 열두 번째 글자부터 다르다는 것을 표시해 줍니다.

# cmp cmp_test cmp_test2
cmp_test cmp_test2 differ: char 12, line 1

 

 

  4. col(개행 문자 변환)

 1) 경로 : /usr/bin/col

 2) 요약 : 텍스트 파일의 개행 문자와 공백 문자 등을 변환하여 문서 속성을 변경

 3) 사용 방법 : col [옵션]

 4) 옵션

 -b : 어떠한 백스페이스 문자도 출력하지 않고, 각 열 위치에 쓰여진 마지막 문자만을 출력

 -h : 중복되는 공백을 출력하지 않음

 -x : 탭을 대신하여 여러 스페이스로 변경하여 출력

 -l(엘) 숫자 : 버퍼 값을 지정. 메모리에 한 번에 올릴 수 있는 최대 줄 수를 지정. 초기값은 128줄

 

 5) 추가 설명

col 필터는 \n\r 문자를 \n 문자로 바꾸거나 공백 문자를 탭 문자로, 백스페이스 문자를 없애는 기능을 합니다.

 

아래는 맨 페이지를 입력으로 받아들여 파일로 저장한 예입니다.

# man httpd | col > httpd.man

 

 

  5. colcrt(밑줄 문자 변환)

 1) 경로 : /usr/bin/colcrt

 2) 요약 : 밑줄(_) 문자를 감추거나 다음 줄에 반줄(-) 속성으로 변환해 주는 필터

 3) 사용 방법 : colcrt [옵션] [파일]

 4) 옵션

 - : 밑줄 속성이 있는 문자열을 출력하지 않음

 -2 : 인쇄상 줄 간격이 이상한 오류가 발생하기 때문에, 밑줄 속성이 있는 줄의 다음 줄에 반줄(-) 속성을 부여하엿고, 없는 줄에는 공백 줄을 추가

 

 5) 추가 설명

colcrt 필터는 밑줄(_) 속성을 반줄(-) 속성으로 바꾸어 주거나, 밑줄 속성을 보이지 않게 할 수 있습니다. 예를 들어 현재 query라는 파일에는 밑줄 문자가 3개가 포함되어 있다고 가정합니다. data_format과 cst_users, cst_productregs 문자입니다.

# cat query
select data_format(uregdate, '%y%m') date,count(uid) from cst_users u, cst_productregs p, cst-productregdetail d
where u.uno=p.preguno
and p.pregno=d.preggno

 

colcrt 필터를 사용하며 밑줄 문자가 한 줄 아래(_)로 표시된 것을 볼 수 있습니다.

# cat query | colcrt
select data_format(uregdate, '%y%m') date,count(uid) from cst_users u, cst_productregs p, cst-productregdetail d
		_					_					_
where u.uno=p.preguno
and p.pregno=d.preggno

 

colcrt -은 밑줄 문자를 출력하지 않게 해줍니다.

# cat query | colcrt -
select data_format(uregdate, '%y%m') date,count(uid) from cst_users u, cst_productregs p, cst-productregdetail d
where u.uno=p.preguno
and p.pregno=d.preggno

 

-2 옵션은 밑줄 속성이 있는 줄의 다음 줄에 (-) 속성을 부여하고, 없는 줄에는 공백 줄을 추가합니다.

# cat query
select data_format(uregdate, '%y%m') date,count(uid) from cst_users u, cst_productregs p, cst-productregdetail d
			-				-				-
where u.uno=p.preguno
and p.pregno=d.preggno
반응형

댓글