본문 바로가기

IT's Life/Linux

리눅스 awk 명령 고급 사용법 완전한 해적


이전 섹션에서는 awk의 기본 사용법을 소개했지만 실제로 awk 스크립트에서는 변수, 배열, 분기 구조 (if-then-else), 루프 구조 (while), 함수 등과 같은 일부 프로그래밍 언어도 지원됩니다. 모두를 위해 하나씩.


변수를 사용하는 awk

awk의 스크립트에서 변수를 사용하여 값에 액세스하는 것이 지원됩니다. Awk는 두 가지 유형의 변수를 지원합니다.

  • 내장 변수 : awk 자체가 생성되고, 사용자가 직접 사용할 수있는 변수이며,이 변수는 일부 필드를 데이터 파일에 저장하고 정보를 기록하는 데 사용됩니다.
  • 맞춤 변수 : awk를 사용하면 변수를 직접 만들 수 있습니다.

내장 변수

awk 프로그램은 내장 변수를 사용하여 프로그램 데이터의 일부 특수 기능을 참조합니다. 공통 내장 변수 중 일부에는 이전 섹션에서 설명한 데이터 필드 변수 ($ 0, $ 1, $ 2 ... $ n)와 표 1 및 표 2에 표시된 변수가 포함됩니다.


표 1 필드 및 레코드 구분자 변수

변수 

기능 

필드 위드 

각 데이터 필드의 정확한 너비를 정의하는 공백으로 구분 된 숫자 열입니다. 

FNR 

여러 입력 문서가있을 때 자주 사용되는 현재 입력 문서의 레코드 번호입니다. 

 NR

입력 스트림의 현재 레코드 번호 

 FS

입력 필드 구분자 

 RS

줄 바꿈 문자 \ n으로 기본 설정되는 레코드 구분 기호를 입력하십시오. 

OFS 

출력 필드 구분 기호는 기본적으로 공백입니다. 

ORS 

출력 레코드 구분 기호, 기본값은 줄 바꾸기 \ n입니다. 

표 1에서 변수 FS 및 OFS는 awk가 데이터 스트림의 데이터 필드를 처리하는 방법을 정의합니다. 변수 FS를 사용하여 레코드에서 필드 구분 기호를 정의하는 방법은 이미 알고 있으며, 변수 OFS는 동일한 기능을 수행하지만 print 명령의 출력에 사용됩니다.

[root @ localhost ~] # cat data1 

data11, data12, data13, data14, data15 

data21, data22, data23, data24, data25 

data31, data32, data33, data34, data35 

[root @ localhost ~] # awk 'BEGIN {FS = " , "; OFS ="- "} {print $ 1, $ 2, $ 3} 'data1 

data11-data12- 

data13 data21-data22-data23 

data31-data32-data33 

[root @ localhost ~] # awk'BEGIN {FS =", " ; OFS = "-"} {print $ 1, $ 2, $ 3} 'data1 

data11--data12-- 

data13 data21--data22--data23 

data31--data32--data33

보시다시피, print 명령은 출력의 각 필드 사이에 OFS 변수 값을 자동으로 배치합니다. OFS 변수를 설정하면 출력에서 ​​임의의 문자열을 사용하여 필드를 분리 할 수 ​​있습니다. 

FIELDWIDTHS 변수를 사용하면 필드 구분 기호에 의존하지 않고 레코드를 읽을 수 있습니다. 일부 응용 프로그램에서는 데이터가 필드 구분 기호를 사용하지 않고 레코드의 특정 열에 배치되므로이 경우 레코드의 데이터 위치와 일치하도록 FIELDWIDTHS 변수를 설정해야합니다. 


FIELDWIDTH 변수가 설정되면 awk는 FS 변수를 무시하고 제공된 필드의 너비를 기준으로 필드를 계산합니다 필드 구분 기호 대신 필드 너비를 사용하는 예는 다음과 같습니다.

[root @ localhost ~] # cat data1b 

1005.3247596.37 

115-2.349194.00 

05810.1298100.1 

[root @ localhost ~] # awk 'BEGIN {FIELDWIDTHS = "3 5 2 5"}} {print $ 1, $ 2, $ 3, $ 4} 'data1b 

100 5.324 75 96.37 

115 -2.34 91 94.00 

058 10.12 98 100.1

FIELDWIDTHS 변수의 값이 설정되면 더 이상 변경할 수 없으므로이 방법은 가변 길이 필드에는 적용되지 않습니다. 

RS 및 ORS 변수는 awk 프로그램이 데이터 스트림에서 필드를 처리하는 방법을 정의하며 기본적으로 awk는 RS 및 ORS를 줄 바꿈 문자로 설정합니다. 기본 RS 값은 입력 데이터 스트림의 각 새 텍스트 행이 새 레코드임을 나타냅니다. 때로는 데이터 스트림에서 여러 행을 차지하는 필드가 나타납니다. 일반적인 예는 주소와 전화 번호가 포함 된 데이터입니다. 여기서 주소와 전화 번호는 각각 한 줄을 차지합니다.


라일리 뮬렌 

123 Main Street 

Chicago, IL 60601 

(312)555-1234

기본 FS 및 RS 변수 값을 사용하여 데이터 세트를 읽는 경우 awk는 각 행을 별도의 레코드로 읽고 레코드의 공백을 필드 구분 기호로 취급하지만 이는 사용자가 원하는 것이 아닙니다. . 

이 문제를 해결하려면 간단히 FS 변수를 줄 바꿈 문자로 설정하십시오. 즉, 데이터 스트림의 각 행은 별도의 필드이고 각 행의 모든 ​​데이터는 동일한 필드에 속하며 동시에 RS 변수가 배치됩니다. 빈 문자열로 설정 한 다음 데이터 레코드 사이에 빈 줄을두면 awk는 각 빈 줄을 레코드 구분 기호로 취급합니다. 예를 들면 다음과 같습니다.

[root @ localhost ~] # cat data2 

Riley Mullen 

123 Main Street 

Chicago, IL 60601 

(312)555-1234 


Frank Williams 

456 Oak Street 

인디애나 폴리스, IN 46201 

(317)555-9876 


Haley Snell 

4231 Elm Street 

Detroit, MI 48201 

(313 ) 555-4938 

[root @ localhost ~] # awk 'BEGIN {FS = "\ n"; RS = ""} {print $ 1, $ 4}'data2 

Riley Mullen (312)555-1234 

Frank Williams (317) 555- 9876 

헤일리 스넬 (313) 555-4938


표 2 환경 정보 변수

변수 이름 

기능 

ARGC  

명령 행 인수의 수 

아르헨티나 

ARGC에서 현재 파일의 위치입니다. 

 ARGV

명령 행 인수를 포함하는 배열입니다. 

 전환

숫자 변환 형식으로, 기본값은 % .6g입니다. 

환경 

현재 쉘 환경 변수 및 해당 값의 연관 배열. 

 ERRNO

입력 파일을 읽거나 닫을 때 오류가 발생하면 시스템 오류 번호입니다. 

FILENAME 

현재 입력 문서의 이름입니다. 

 FNR

현재 데이터 파일의 데이터 행 수입니다. 

 무시

 0이 아닌 값으로 설정하면 awk 명령에 나타나는 문자열의 대소 문자가 무시됩니다.

 NF

데이터 파일의 총 필드 수입니다. 

 NR

처리 된 입력 레코드 수 

 OFMT

숫자의 출력 형식으로, 기본값은 % .6g입니다. 

 링 게스

일치 함수와 일치하는 부분 문자열의 길이입니다. 

TSTART 

일치 함수와 일치하는 부분 문자열의 시작 위치입니다. 

그중에서도 FNR과 NR 변수는 비슷하지만 약간 다릅니다. FNR 변수에는 현재 데이터 파일에서 처리 된 레코드 수가 포함되고 NR 변수에는 처리 된 총 레코드 수가 포함됩니다. 예를 들면 다음과 같습니다.

[root @ localhost ~] # cat data1 

data11, data12, data13, data14, data15 

data21, data22, data23, data24, data25 

data31, data32, data33, data34, data35 

[root @ localhost ~] # awk ' 

> BEGIN {FS = ","} 

> {print $ 1, "FNR ="FNR, "NR ="NR} 

> END {인쇄 "있었습니다", NR, "레코드 처리됨"} 'data1 data1 

data11 FNR = 1 NR = 1 

data21 FNR = 2 NR = 2 데이터 

31 FNR = 3 NR = 3 데이터 

11 FNR = 1 NR = 4 데이터 

21 FNR = 2 NR = 5 데이터 

31 FNR = 3 NR = 6 

6 개의 레코드가 처리되었습니다.

하나의 데이터 파일 만 입력으로 사용하는 경우 FNR과 NR의 값이 동일 함을 알 수 있습니다. 여러 데이터 파일을 입력으로 사용하는 경우 각 데이터 파일을 처리 할 때 FNR의 값이 재설정됩니다. NR 값은 모든 데이터 파일이 처리 될 때까지 계속 계산됩니다.


맞춤 변수

다른 일반적인 프로그래밍 언어와 마찬가지로 awk를 사용하면 스크립트에서 사용할 고유 변수를 정의 할 수 있습니다. Awk 사용자 정의 변수 이름은 문자, 숫자 및 밑줄 수에 제한이 없지만 숫자로 시작할 수 없습니다. 더 중요한 것은 awk 변수 이름은 대소 문자를 구분하는 것입니다. 

간단한 예를 들면 다음과 같습니다.

[root @ localhost ~] # awk ' 

> BEGIN { 

> testing = "테스트입니다" 

> 인쇄 테스트 

> testing = 45 

> 인쇄 테스트 

>}' 

이것은 테스트입니다 

45

보시다시피, print 문의 출력은 테스트 변수의 현재 값입니다. 

awk 명령 줄을 사용하여 프로그램의 변수에 값을 할당 할 수도 있습니다.이를 통해 일반 코드 외부에서 값을 할당하고 다음과 같이 변수 값을 즉시 변경할 수 있습니다.

[root @ localhost ~] # cat script1 

BEGIN {FS = ","} {print $ n} 

[root @ localhost ~] # awk -f script1 n = 2 data1 

data12 

data22 

data32 

[root @ localhost ~] # awk -f = N-DATAl. 3 script1이 

DATA13 

DATA23의 

data33


변수 값을 정의하기 위해 명령 줄 인수를 사용하는 데 문제가 있다는 점에 유의해야합니다. 변수를 설정 한 후에는 아래 그림과 같이 코드의 BEGIN 부분에서이 값을 사용할 수 없습니다.

[root @ localhost ~] # cat script2 

BEGIN {print "시작 값은", n; FS = ","} 

{print $ n} 

[root @ localhost ~] # awk -f script2 n = 3 data1 

시작 값 데이터 

13 

데이터 

23 데이터 33

이 문제를 해결하려면 -v 명령 행 인수를 사용하면 BEGIN 코드 전에 변수를 설정할 수 있습니다. 명령 행에서 -v 명령 행 인수는 다음과 같이 스크립트 코드 앞에 있어야합니다.

[루트 @ 로컬 호스트는 ~] # = -vn AWK -f SCRIPT2 DATAl. 3 

시작 값 중입니다. 3 

DATA13 

DATA23의 

data33

awk 스크립트의 출력 함수는 C 언어의 printf 함수를 사용할 수도 있습니다. 자세한 내용은 " C 언어 printf 함수 "및 " C 언어 출력 요약 " 이라는 두 기사를 읽고이 함수 를 사용하는 방법을 배우십시오.


배열을 사용하는 awk

단일 변수에 여러 값을 저장하기 위해 많은 프로그래밍 언어가 배열을 제공하고 awk는 연관 배열을 사용하여 배열 기능을 제공합니다. 

연관 배열은 인덱스 값이 텍스트 문자열 일 수 있다는 점에서 숫자 배열과 다릅니다. 사용자는 배열에서 데이터 요소를 식별하기 위해 연속 숫자를 사용할 필요가 없으며, 연관 배열은 다양한 문자열을 사용하여 값을 참조합니다. 각 인덱스 문자열은 할당 된 데이터 요소를 고유하게 식별 할 수 있어야합니다.

다른 프로그래밍 언어에 익숙한 경우 연관 배열을 사용하는 것은 해시 테이블 및 사전과 유사합니다.


연관 배열의 정의 및 사용

awk 스크립트에서 배열 변수를 정의하면 표준 copy 문을 사용할 수 있습니다. 기본 형식은 다음과 같습니다.

Var [index] = 요소

var는 배열 이름이고 index는 연관 배열의 인덱스 값이고 element는 데이터 요소 값입니다. 예를 들면 다음과 같습니다.

수도 [ "일리노이"] = " 스프링 필드" 

수도 [ "인디아나"] = "인디아나 폴리스" 

수도 [ "오하이오"] = "콜럼버스"


배열 변수를 참조 할 때 인덱스 값 (인덱스)을 사용하여 해당 데이터 요소 값을 추출해야합니다. 예를 들면 다음과 같습니다.

[root @ localhost ~] # awk 'BEGIN { 

> capital [ "일리노이"] = "스프링 필드" 

> 인쇄본 [ "일리노이"] 

>}' 

스프링 필드

배열 변수도 변수이며 다음과 같은 기본 산술 연산에 사용할 수 있습니다.

[root @ localhost ~] # awk 'BEGIN { 

> var [1] = 34 

> var [2] = 3 

> 총계 = var [1] + var [2] 

> 총계 인쇄 

>}' 

37


연관 배열의 순회

awk에서 연관 배열을 순회하면 특별한 형식의 for 문을 사용할 수 있습니다.

for (배열의 var) 

    문 

}


이 for 문은 루프 될 때마다 연결된 배열 배열의 다음 인덱스 값을 변수 var에 할당 한 다음 명령문을 한 번 실행합니다.

또한 순회 프로세스 전체에서 var은 배열 요소의 값이 아니라 각 배열 요소의 인덱스 값 (즉, 인덱스)으로 전달됩니다.

예를 들면 다음과 같습니다.

[root @ localhost ~] # awk 'BEGIN { 

> var [ "a"] = 1 

> var [ "g"] = 2 

> var [ "m"] = 3 

> var [ "u"] = 4 

> for ( var에서 테스트) 

> { 

> print "Index :", test, "-Value :", var [test] 

>} 

>} ' 

인덱스 : u-값 : 4 

인덱스 : m-값 : 3 

인덱스 : a-값 : 1 

색인 : g-값 : 2

인덱스 값은 특정 순서로 반환되지 않지만 모두 해당 데이터 요소 값을 가리 킵니다.


배열 변수 삭제

awk 스크립트는 또한 연관 배열에서 배열 인덱스 삭제를 지원합니다 delete 명령을 사용하면 지정된 인덱스 값과 관련 데이터 요소 값을 배열에서 제거 할 수 있습니다. 

delete 명령의 기본 형식은 다음과 같습니다.

배열 삭제 [색인]

예를 들면 다음과 같습니다.

[root @ localhost ~] # awk 'BEGIN { 

> var [ "a"] = 1 

> var [ "g"] = 2 

> for (var에서 테스트) 

> { 

> print "Index :", test, "-값 : ", var [test] 

>} 

> delete var ["g "] 

> print"--- " 

> for (var에서 테스트) 

> { 

> print"Index : ", test,"-Value : ", var [ 테스트] 

>} 

>} ' 

인덱스 : a-값 : 1 

인덱스 : g-값 : 2 

--- 

인덱스 : a- 값 : 1

일단 인덱스 값이 연관 배열에서 제거되면 요소 값을 추출 할 수있는 방법이 없습니다.


Awk는 분기 구조를 사용합니다

Awk는 기본 if-then-else 형식 if 문을 지원하며 기본 형식은 다음과 같습니다.

if (조건) 

    statement1 

else 

    문


다음과 같이 한 줄에 넣을 수도 있습니다.

if (조건) statement1; else statement2


간단한 예를 들면 다음과 같습니다.

[root @ localhost ~] # cat data4 

10 

13 

50 

34 

[root @ localhost ~] # awk '{if ($ 1> 20) print $ 1 * 2; else print $ 1 / 2}'data4 

2.5 

6.5 

100 

68


Awk는 루프 구조를 사용합니다

awk 스크립트에서 세 가지 루프 구조를 사용할 수 있습니다 : while, dowwhile 및 for. 기본 형식은 표 3에 나와 있습니다.

루프 구조의 기본 형식 및 예

기본 형식

인스턴스 

While (조건) { 

   실행 코드; 

}

[루트 @ 로컬 호스트 ~] #에 CAT DATA5 

130 120 135 

160 113 140 

145 170 215 

[루트 @ 로컬 호스트 ~] #에 AWK '{ 

> 총 = 0 

> I =. 1 

>은 잠시 (I는 <. 4) 

> { 

> 총 + = $ i 

> i ++ 

>} 

> avg = total / 3 

> print "Average :", avg 

>} 'data5 

평균 : 128.333 

평균 : 137.667 

평균 : 176.667 

 할 

실행 코드를; 

}는 동안 (상태)

[루트 @ localhost를 ~] #의 AWK를 '{ 

> 총 = 0 

>. 1 = I 

> 할 

> { 

> $ 총 + I = 

> 나는 ++ 

>}는 동안 (총 <150) 

> 전체 인쇄}'DATA5 

250 

(160) 

(315) 

 (변수; 조건; 카운터) 

    실행 코드; 

}

[root @ localhost ~] # awk '{ 

> total = 0 

> for (i = 1; i <4; i ++) 

> { 

> total + = $ i 

>} 

> avg = total / 3 

> "Average :"인쇄 AVG 

>} 'DATA5의 

평균 : 128.333 

평균 : 137.667 

평균 : 176.667 

표 3에서 볼 수 있듯이 awk가 지원하는 루프 구조의 사용은 C 언어와 동일하며 awk는 중단 (breakout loop), 계속 (현재 루프 종료) 키워드, 사용법 및 C의 사용을 지원합니다. 이 언어는 정확히 동일합니다. 더 이상 논의가 없습니다 독자는 " C 언어 루프 구조 및 선택 구조 "장을 체계적으로 읽을 수 있습니다 .


어크 사용 기능

내장 기능

내장 변수와 유사하게 awk는 표 4에 표시된 것처럼 일반적인 수학, 문자열 및 시간 함수 연산을 수행하기위한 여러 내장 함수도 제공합니다.

표 4 awk 내장 함수

타임 스탬프는 1970 년 1 월 1 일 8 : 1부터 현재 총 초 수까지의 그리니치 평균시를 나타냅니다.


커스텀 기능

awk의 내장 함수 외에도 awk 스크립트에서 함수를 사용자 정의 할 수 있습니다 사용자 정의 함수를 작성하기위한 기본 형식은 다음과 같습니다.

함수 이름 (매개 변수 1, 매개 변수 2, ...) 

    실행 코드; 

}


사용자 정의 함수의 함수 이름은이 함수를 고유하게 식별 할 수 있어야합니다. 즉, 동일한 awk 스크립트에서 여러 함수의 함수 이름은 동일 할 수 없습니다. 동시에 함수의 매개 변수는 여러 개 (0, 1 이상)를 가질 수 있습니다. 


예를 들면 다음과 같습니다.

함수 printthird () 

    print $ 3 

}


이 기능은 레코드의 세 번째 데이터 필드를 인쇄합니다. 


이 함수는 return 문을 사용하여 값을 반환 할 수도 있습니다. 예를 들면 다음과 같습니다.

함수 myrand (limit) { 

    return int (limit * rand ()) 

}

함수를 정의 할 때 모든 코드 블록 (BEGIN 및 END 코드 블록 포함) 앞에 나타나야합니다.


함수 라이브러리 생성

Awk는 사용자가 모든 awk 스크립트에서 사용할 수 있도록 라이브러리 파일에 여러 함수를 넣는 방법을 제공합니다. 모든 사람의 이해를 돕기 위해 예를 들어 보겠습니다. 


먼저 모든 awk 함수를 저장하는 파일을 만들어야합니다.

[root @ localhost ~] # cat funclib 

함수 myprint () { 

   printf "% -16s- % s \ n", $ 1, $ 4 

function myrand (limit) 

   return int (limit * rand ()) 

function printthird () 

   인쇄 $ 3 

}


awk가 funclib 라이브러리 파일을 성공적으로 읽으려면 -f 옵션을 사용해야하지만이 옵션은 명령 행에서 awk 스크립트와 함께 사용할 수 없습니다. 따라서 라이브러리 함수 파일을 사용하려면 다음과 같은 다른 스크립트 파일 만 작성할 수 있습니다.

[root @ localhost ~] # cat script4 

BEGIN {FS = "\ n"; RS = ""} 

     myprint () 

[root @ localhost ~] # awk -f funclib -f script4 data2 

Riley Mullen- (312) 555 -1234 

Frank Williams-(317)555-9876 

헤일리 스넬-(313)555-4938