이 텍스트는 gawk Witch라고 알려진 awk 의 GNU 구현 만 가장 많이 사용되며 최신 Linux / Unix 배포와 함께 제공됩니다.
[gnu awk 사용자 안내서] [gnu-awk]는 그 참조입니다. 주로 [stackoverflow] [so] 답변에서 가져온 실제 세계 사례를 사용했습니다.
AWK는 Perl과 비슷한 언어이며 훨씬 더 우아합니다.
- 아놀드 로빈스
AWK는 텍스트 처리 용으로 설계된 프로그래밍 언어이며 일반적으로 데이터 추출 및보고 도구로 사용됩니다. 대부분의 UNIX와 같은 운영 체제의 표준 기능입니다.
awk 상 이름 ...그 이름은 Alfred A Ho, Peter W Einberger 및 Brian K Ernighan의 작가의 성에서 파생되었습니다.
awk ...파일 또는 표준 입력에 특정 패턴이 포함 된 줄을 검색합니다.
다른 유틸리티 프로그램의 출력에서 정보를 요약하는 것과 같은 데이터 추출 및보고에 주로 사용됩니다.
C-like 구문.
데이터 중심 : 작업하려는 데이터와 찾을 때 수행 할 조치를 설명합니다.
pattern { action }
pattern { action }프로그램이 짧은 경우 :
awk ' program ' input-file1 input-file2참고 : 쉘 견적 문제 1 .
cmd | awk ' program ' 참고 : pipe 왼쪽 명령 ( cmd )의 출력을 awk 명령 2 의 입력 으로 리디렉션합니다.
코드가 길면 일반적으로 파일에 넣고 다음과 같은 명령으로 실행하는 것이 더 편리합니다.
awk -f program-file input-file1 input-file2
cmd | awk -f program-file 또는 shebang 처럼 실행할 수 있도록하십시오.
#! /bin/awk -f
BEGIN { print " hello world!! " } -F fs FS 변수를 fs 로 설정합니다.
-v var=val 프로그램 실행을 시작하기 전에 변수 var value val 로 설정했습니다.
참고 : 매번 다른 변수를 설정하여 두 번 이상 사용할 수 있습니다.
이러한 특별한 패턴 또는 블록은 awk 프로그램을위한 스타트 업 및 정리 작업을 공급합니다.
BEGIN{
// initialize variables
}
{
/pattern/ { action }
}
END{
// cleanup
}BEGIN 모든 입력이 소비 된 후 END .
$ echo " hello " | awk ' BEGIN{print "BEGIN";f=1}
{print $f}
END{print "END"} '
BEGIN
hello
ENDawk 하면 왜 grepping ?? $ cat lorem_ipsum.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.$ grep dolor lorem_ipsum.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.$ awk ' /dolor/ ' lorem_ipsum.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.참고 : 작업에 주어지지 않은 경우 기본 조치는 주어진 패턴과 일치하는 레코드를 인쇄하는 것입니다.
그러나 ... 각 줄의 첫 번째 와 마지막 단어를 어떻게 알 수 있습니까?
물론 grep 할 수 있지만 두 단계가 필요합니다.
$ grep -Eo ' ^[^ ]+ ' lorem_ipsum.dat
Lorem
Maecenas
Nunc
Curabitur
Lorem
Aliquam$ grep -Eo ' [^ ]+$ ' lorem_ipsum.dat
elit.
condimentum.
ex.
tellus.
elit.
ultrices. 여기서 awk 보자.
$ awk ' {print $1,$NF} ' lorem_ipsum.dat
Lorem elit.
Maecenas condimentum.
Nunc ex.
Curabitur tellus.
Lorem elit.
Aliquam ultrices. awk 프로그램 입력을 레코드 및 필드 로 나눕니다.
레코드 는 레코드 분리기 RS 라는 문자로 분리됩니다. 기본적으로 레코드 분리기는 Unix Newline 문자 n 입니다.
이것이 기본적으로 단일 라인 인 이유입니다.
또한 awk 에는 ORS 출력 레코드 분리기 가있어 레코드가 stdout 에 제시되는 방식을 제어합니다.
RS 와 ORS 인용 표시 로 둘러싸여 있어야하며 문자열 상수를 나타냅니다.
다른 문자를 사용하거나 Regex를 사용하려면 단순히 RS 또는 / 및 ORS 변수에 할당합니다.
BEGIN 므로 첫 번째 레코드는 적절한 분리기와 함께 읽습니다.예 :
$ awk ' BEGIN{RS=" *, *";ORS="<<<---n"}
{print $0} ' lorem_ipsum.dat
Lorem ipsum dolor sit amet <<< ---
consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci <<< ---
euismod id nisi eget <<< ---
interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet <<< ---
consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat <<< ---
et facilisis neque ultrices.
<<< --- $ awk ' {print $0} ' RS= " *, * " ORS= " <<<---n " lorem_ipsum.dat
Lorem ipsum dolor sit amet <<< ---
consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci <<< ---
euismod id nisi eget <<< ---
interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet <<< ---
consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat <<< ---
et facilisis neque ultrices.
<<< --- awk 레코드는 자동으로 구문 분석되거나 필드 라고하는 청크 로 분리됩니다.
기본적으로 필드는 한 줄의 단어와 같이 공백 (하나 이상의 공백, 탭 또는 신축성)으로 분리됩니다.
awk 프로그램의 필드를 참조하려면 달러 $ 표시와 원하는 필드 수를 사용합니다.
따라서 $1 첫 번째 필드, $2 번째 필드 등을 나타냅니다.
중요 : $0 전체 입력 레코드를 나타냅니다.
$ awk ' {print $3} ' lorem_ipsum.dat
dolor
erat
orci,
dapibus
dolor
mauris NF 사전 정의 된 변수입니다. 값은 현재 레코드의 필드 수 입니다. 따라서 $NF 항상 레코드의 마지막 필드가 될 것입니다.
$ awk ' {print NF} ' lorem_ipsum.dat
8
7
10
4
8
10vs.
$ awk ' {print $NF} ' lorem_ipsum.dat
elit.
condimentum.
ex.
tellus.
elit.
facilisis. FS 필드 분리기 의 가치를 보유하고 있으며,이 값은 단일 문자열 또는 입력 레코드에서 필드 간의 분리와 일치하는 단일 문자열 또는 regex 입니다.
기본값은 단일 공간으로 구성된 문자열 인 " " 입니다. 특별한 예외로,이 값은 모든 공백 , 탭 및/또는 신성술 순서가 단일 분리기임을 의미합니다.
ORS 와 같은 방식으로 우리는 OFS 변수를 가지고 있으며 필드가 출력 스트림으로 전송되는 방식을 관리합니다.
$ cat /etc/group
nobody: * :-2:
nogroup: * :-1:
wheel: * :0:root
daemon: * :1:root
kmem: * :2:root
sys: * :3:root
tty: * :4:root$ awk ' !/^(_|#)/&&$1=$1 ' FS= " : " OFS= " <-> " /etc/group
nobody < - > * < - > - 2< - >
nogroup < - > * < - > - 1< - >
wheel < - > * < - > 0 < - > root
daemon < - > * < - > 1 < - > root
kmem < - > * < - > 2 < - > root
sys < - > * < - > 3 < - > root
tty < - > * < - > 4 < - > root 참고 : 음 ... $1=$1 ???? 3
레코드 와 필드를 염두에두고 이전 코드를 이해할 준비가되었습니다.
$ awk ' {print $1,$NF} ' lorem_ipsum.dat
Lorem elit.
Maecenas condimentum.
Nunc ex.
Curabitur tellus.
Lorem elit.
Aliquam ultrices.이들은 유용한 내장 변수입니다.
NR : 프로그램 실행이 시작된 이후 awk 처리 한 입력 레코드 수입니다.
FNR : 현재 파일의 현재 레코드 번호는 새 입력 파일을 시작할 때 awk FNR 0 으로 재설정합니다.
$ cat n1.dat
one
two$ cat n2.dat
three
four$ awk ' {print NR,FNR,$0} ' n1.dat n2.dat
1 1 one
2 2 two
3 1 three
4 2 four형식 문자열은 ISO C 의 형식과 매우 유사합니다.
통사론:
printf format, item1, item2, …
$ awk ' {printf "%20s <-> %sn",$1,$NF} ' lorem_ipsum.dat
Lorem < - > elit.
Maecenas < - > condimentum.
Nunc < - > ex.
Curabitur < - > tellus.
Lorem < - > elit.
Aliquam < - > ultrices. print 및 printf 의 출력은 기본적으로 표준 출력 으로 표시되지만 리디렉션을 사용하여 대상을 변경할 수 있습니다.
awk 의 리디렉션은 awk 프로그램 내부에 쓰여진 것을 제외하고 쉘 명령의 리디렉션과 마찬가지로 작성됩니다.
$ awk ' BEGIN{print "hello">"hello.dat"} ' $ awk ' BEGIN{print "world!">>"hello.dat"} ' $ cat hello.dat
hello
world !파이프를 통해 다른 프로그램에 출력을 보낼 수도 있습니다.
$ awk ' BEGIN{sh="/bin/sh";print "date"|sh;close(sh)} '
dom nov 13 18:36:25 CET 2016 [스트림]은 stdin , stdout 및 stderr 를 가리킬 수 있습니다.
예를 들어, 우리는 다음과 같이 stderr 에 오류 메시지를 쓸 수 있습니다.
$ awk ' BEGIN{print "Serious error detected!" > "/dev/stderr"} '
Serious error detected ! awk에서 어레이는 연관성이 있으며, 각 배열은 쌍 , 색인 - 값 의 모음이며, 여기서 숫자 또는 문자열은 인덱스가 될 수 있습니다.
선언이 필요하지 않습니다. 언제든지 새로운 쌍을 추가 할 수 있습니다.
| 색인 | 값 |
|---|---|
| "페로" | "개" |
| "가토" | "고양이" |
| "우노" | "하나" |
| 1 | "하나" |
| 2 | "둘" |
배열을 참조하려면 :
array[index-expression]
값을 할당하려면 :
array[index-expression] = value
키가 색인되어 있는지 확인하려면 :
indx in array
반복하기 위해 :
for (var in array) {
var, array[var]
}숫자 값을 인덱스로 사용하고 순서 보존 :
for (i = 1 ; i < = max_index ; i++) {
print array[i]
}완전한 예 :
$ cat dict.dat
uno one
dos two
tres three
cuatro fourawk ' {dict[$1]=$2}
END{if ("uno" in dict)
print "Yes we have uno in dict!"
if (!("cinco" in dict))
print "No , cinco is not in dict!"
for (esp in dict){
print esp, "->" ,dict[esp]
}
} ' dict.dat당신에게 :
Yes we have uno in dict !
No , cinco is not in dict !
uno - > one
dos - > two
tres - > three
cuatro - > four gawk 기본적으로 배열을 정렬하지 않습니다.
awk ' BEGIN{
a[4]="four"
a[1]="one"
a[3]="three"
a[2]="two"
a[0]="zero"
exit
}
END{for (idx in a){
print idx, a[idx]
}
} ' 4 four
0 zero
1 one
2 two
3 three그러나 정렬을 위해 [Procinfo]를 활용할 수 있습니다.
awk ' BEGIN{
PROCINFO["sorted_in"] = "@ind_num_asc"
a[4]="four"
a[1]="one"
a[3]="three"
a[2]="two"
a[0]="zero"
exit
}
END{for (idx in a){
print idx, a[idx]
}
} ' 0 zero
1 one
2 two
3 three
4 four gensub(regexp, replacement, how [, target]) : 문자열 교체의 가장 진보 된 기능입니다.
그리고 그들의 간단한 대안 :
gsub(regexp, replacement [, target])
sub(regexp, replacement [, target])
이 파일이 있습니다 :
$ cat lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.우리는 각 쉼표의 왼쪽 과 오른쪽 에있는 단어의 위치를 교환 할 것입니다.
$ awk ' {print gensub(/([^ ]+)( *, *)([^ ]+)/,
"\3\2\1", "g")} ' lorem.dat
Lorem ipsum dolor sit consectetur, amet adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim euismod, orci id nisi interdum, eget cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit consectetur, amet adipiscing elit.
Aliquam interdum mauris volutpat nisl et, placerat facilisis. gensub 사용하여 세 그룹을 캡처 한 다음 주문을 교환합니다.
더 간단한 액션을 설명하기 위해 쉼표 에 대한 점을 변경하겠습니다.
awk ' $0=gensub(/./, ",", "g") ' lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Maecenas pellentesque erat vel tortor consectetur condimentum,
Nunc enim orci, euismod id nisi eget, interdum cursus ex,
Curabitur a dapibus tellus,
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Aliquam interdum mauris volutpat nisl placerat, et facilisis, gsub 대안 사용 :
awk ' gsub(/./, ",") ' lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Maecenas pellentesque erat vel tortor consectetur condimentum,
Nunc enim orci, euismod id nisi eget, interdum cursus ex,
Curabitur a dapibus tellus,
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Aliquam interdum mauris volutpat nisl placerat, et facilisis,이 옵션은 그룹 캡처가 필요하지 않은 경우 더 좋아 보입니다.
다른 흥미로운 기능은 index 및 substr 입니다.
index(in, find)
substr(string, start [, length ])
다음과 같이 작동합니다.
$ awk ' BEGIN{t="hello-world";print index(t, "-")} '
6$ awk ' BEGIN{t="hello-world";print substr(t,index(t, "-")+1)} '
world split 함수는 분리기 숯 으로 나누는 문자열에서 배열을 만드는 데 사용되며 생성 된 배열의 요소 수를 반환합니다.
split(string, array [, fieldsep [, seps ] ])
$ cat passwd
jd001:x:1032:666:Javier Diaz:/home/jd001:/bin/rbash
ag002:x:8050:668:Alejandro Gonzalez:/home/ag002:/bin/rbash
jp003:x:1000:666:Jose Perez:/home/jp003:/bin/bash
ms004:x:8051:668:Maria Saenz:/home/ms004:/bin/rbash
rc005:x:6550:668:Rosa Camacho:/home/rc005:/bin/rbash$ awk ' n=split($0, a, ":"){print n, a[n]} ' passwd
7 /bin/rbash
7 /bin/rbash
7 /bin/bash
7 /bin/rbash
7 /bin/rbash참고 : 이것은 훨씬 더 간단한 방식으로 수행 할 수 있습니다.
$ awk ' {print NF,$NF} ' FS= ' : ' passwd
7 /bin/rbash
7 /bin/rbash
7 /bin/bash
7 /bin/rbash
7 /bin/rbash사용자 정의 기능 작성은 매우 간단합니다.
awk ' function test(m)
{
printf "This is a test func, parameter: %sn", m
}
BEGIN{test("param")} '우리에게 줘 :
This is a test func, parameter: param 우리는 또한 return 명령문을 사용하여 표현을 돌려 줄 수 있습니다.
awk ' function test(m)
{
return sprintf("This is a test func, parameter: %s", m)
}
BEGIN{print test("param")} '매개 변수 별 구문 분석은 함수 내에서 로컬 변수를 만드는 유일한 방법입니다.
스칼라 값은 참조별로 값과 배열로 전달되므로 함수 내부의 배열로 변경되는 모든 변경 사항은 글로벌 범위에 반영됩니다.
awk ' function test(m)
{
m[0] = "new"
}
BEGIN{m[0]=1
test(m)
exit
}
END{print m[0]} '출력 :
new우리의 도전 :
01. 기록의 두 번째 단어.
02. 레코드 교체.
03. 각 레코드의 끝에 세미콜론을 놓습니다.
04. 모든 단어 사이에 쉼표를 놓습니다.
05. 모두 함께?
06. 홀수 레코드를 파일로 그리고 심지어 다른 파일로 리디렉션합니다.
07. 비밀번호 파일이 주어지면 누락 된 필드를 가져옵니다.
08. 필드 교환.
09. Traceroute 해킹.
10. 내 아이들은 어디에 있습니까?
11. 데이터 집계.
12. 두 패턴 사이의 기록.
13. 필드 변환.
14. 열에 기록.
15. FASTA 파일 처리.
16. 복잡한보고.
17. 파일 조인기.
18. Passwd와 Group.
19. 사용자 연결.
20. 가동 시간 총 부하 평균.
이 소스 파일이 있습니다 :
$ cat lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.$ awk ' {print $(NF-1)} ' lorem.dat
adipiscing
consectetur
cursus
dapibus
adipiscing
neque 여기서 설명하기에는 그리 많지 않은 NF 현재 레코드의 필드 수를 저장하므로 NF-1 마지막으로 필드를 가리키고 $(NF-1) 그 가치가됩니다.
우리의 과제, 파일 레코드 대체, 세 번째 줄은 다음과 같습니다.
This not latin
더 간단한 것은없고, NR ( 레코드 수 )을 플레이하십시오.
암호:
$ awk ' NR==3{print "This is not latin";next}{print} ' lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
This is not latin
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis. next 진술을 피하기위한 대체 솔루션 : 새 라인을 전체 레코드에 $0 에 할당하십시오.
예:
$ awk ' NR==3{$0="This is not latin"}1 ' lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
This is not latin
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.$ awk ' 1 ' ORS= " ;n " lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ;
Maecenas pellentesque erat vel tortor consectetur condimentum. ;
Nunc enim orci, euismod id nisi eget, interdum cursus ex. ;
Curabitur a dapibus tellus. ;
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ;
Aliquam interdum mauris volutpat nisl placerat, et facilisis neque ultrices. ; 기본 RS 는 Unix Break Line n 세미콜론을 출력 레코드 OFS 에 접두사 해야합니다.
1 어떻습니까? 4
$ awk ' {$1=$1}1 ' OFS= ' , ' lorem.dat
Lorem,ipsum,dolor,sit,amet,,consectetur,adipiscing,elit.
Maecenas,pellentesque,erat,vel,tortor,consectetur,condimentum.
Nunc,enim,orci,,euismod,id,nisi,eget,,interdum,cursus,ex.
Curabitur,a,dapibus,tellus.
Lorem,ipsum,dolor,sit,amet,,consectetur,adipiscing,elit.
Aliquam,interdum,mauris,volutpat,nisl,placerat,,et,facilisis,neque,ultrices. 이 코드의 가장 중요한 부분은 OFS 의 현재 가치에 대해 $1=$1 의 레코드 재구성을 강요하는 방법입니다.
$ awk ' {$1=$1}1 ' OFS= ' , ' ORS= ' ;n ' lorem.dat
Lorem,ipsum,dolor,sit,amet,,consectetur,adipiscing,elit. ;
Maecenas,pellentesque,erat,vel,tortor,consectetur,condimentum. ;
Nunc,enim,orci,,euismod,id,nisi,eget,,interdum,cursus,ex. ;
Curabitur,a,dapibus,tellus. ;
Lorem,ipsum,dolor,sit,amet,,consectetur,adipiscing,elit. ;
Aliquam,interdum,mauris,volutpat,nisl,placerat,,et,facilisis,neque,ultrices. ; 출력 vars : OFS and ORS 와 함께
최종 해결책부터 시작하겠습니다.
$ awk ' NR%2{print > "even.dat";next}
{print > "odd.dat"} ' lorem.dat$ cat even.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Lorem ipsum dolor sit amet, consectetur adipiscing elit$ cat odd.dat
Maecenas pellentesque erat vel tortor consectetur condimentum.
Curabitur a dapibus tellus.
Aliquam interdum mauris volutpat nisl placerat, et facilisis. [modulo] 함수 ( % )는 현재 레코드 번호 NR 에 대한 나머지 부문을 찾습니다 .
$ awk ' {print NR%2} ' lorem.dat
1
0
1
0
1
0 우리가 지금까지, awk 1 사실 이고 0 거짓 입니다. 이 사실을 평가하는 출력을 리디렉션합니다.
next 특별한주의가 필요합니다. 이는 현재 레코드 프로세스를 즉시 중지하고 다음과 같이 전달하도록 awk 강요합니다 .
이런 식으로 우리는 다음과 같이 보이는 이중 조건을 피합니다.
awk ' NR % 2{print > "even.dat"}
!NR % 2{print > "odd.dat"} ' lorem.dat$ cat /etc/passwd
jd001:x:1032:666:Javier Diaz::/bin/rbash
ag002:x:8050:668:Alejandro Gonzalez::/bin/rbash
jp003:x:1000:666:Jose Perez::/bin/bash
ms004:x:8051:668:Maria Saenz::/bin/rbash
rc005:x:6550:668:Rosa Camacho::/bin/rbash 고정 문자열 "/home/" 사용자 이름 에 접두사하여 홈 디렉토리를 가정 해 봅시다.
$ awk ' $6="/home/"$1 ' FS= ' : ' OFS= ' : ' /etc/passwd
jd001:x:1032:666:Javier Diaz:/home/jd001:/bin/rbash
ag002:x:8050:668:Alejandro Gonzalez:/home/ag002:/bin/rbash
jp003:x:1000:666:Jose Perez:/home/jp003:/bin/bash
ms004:x:8051:668:Maria Saenz:/home/ms004:/bin/rbash
rc005:x:6550:668:Rosa Camacho:/home/rc005:/bin/rbash우리의 첫 번째 단계는 입력 및 출력을 위해 필드 분리기, 콜론을 고려해야합니다.
그런 다음이 예제에 대해 공허 필드 위치 6 찾아야합니다.
마지막으로, 주어진 문자열과 첫 번째 필드에 저장된 사용자 로그인을 사용하여 필요한 값을 작성합니다.
$6 할당 반환 값이 항상 사실 이므로 print 필요하지 않습니다. awk 기본 조치는 영향을받는 레코드를 인쇄하는 것입니다.
우리의 목표 : 마지막 필드는 첫 번째가되어 첫 번째가되어야합니다.
최종 코드 :
$ awk -F : ' {last=$1;$1=$NF;$NF=last}1 ' FS= " : " OFS= ' : ' /etc/passwd
/bin/rbash:x:1032:666:Javier Diaz:/home/jd001:jd001
/bin/rbash:x:8050:668:Alejandro Gonzalez:/home/ag002:ag002
/bin/bash:x:1000:666:Jose Perez:/home/jp003:jp003
/bin/rbash:x:8051:668:Maria Saenz:/home/ms004:ms004
/bin/rbash:x:6550:668:Rosa Camacho:/home/rc005:rc005 우리는 첫 번째 필드 값을 저장하는 데 사용되는 중간 변수를 사용하고 있습니다. 우리는 그 값을 마지막으로 바꾸고 마지막으로 last 변수를 $NF ( $NF=last )에 할당합니다.
이 출력 :
$ traceroute -q 1 google.com 2> /dev/null
1 hitronhub.home (192.168.1.1) 5.578 ms
2 217.217.0.1.dyn.user.ono.com (217.217.0.1) 9.732 ms
3 10.127.54.181 (10.127.54.181) 10.198 ms
4 62.42.228.62.static.user.ono.com (62.42.228.62) 35.519 ms
5 72.14.235.20 (72.14.235.20) 26.003 ms
6 216.239.50.133 (216.239.50.133) 25.678 ms
7 mad01s24-in-f14.1e100.net (216.58.211.238) 25.019 ms총 시간 여행 패키지를 계산해야합니다.
$ traceroute -q 1 google.com 2> /dev/null |
awk ' {total+=$(NF-1)}
END{print "Total ms: "total} '
Total ms: 153.424조건이 지정되지 않으므로 모든 레코드에 대해 조치가 실행됩니다.
total+=$(NF-1) : total 변수는 각 레코드 두 번째 필드 $(NF-1) 의 값을 축적하는 데 사용됩니다.
마지막으로 END 규칙을 사용하여 최종 total 값을 표시합니다.
우리의 직업 : shell 종속 프로세스를 얻으십시오.
$ echo $$
51026첫 번째 : 배경 프로세스를 시작하십시오.
$ sleep 10 & sleep 15 & sleep 20 &
[1] 86751
[2] 86752
[3] 86753 ps 유틸리티를 사용하여 awk PPID 로 알려진 세 번째 필드를 찾습니다.
참고 : 프로그램 실행을 시작하기 전에 -v 사용하여 PPID VAR을 설정합니다.
$ ps -ef | awk -v ppid= $$ ' $3==ppid '
501 86751 51026 0 7:57PM ttys001 0:00.00 sleep 10
501 86752 51026 0 7:57PM ttys001 0:00.00 sleep 15
501 86753 51026 0 7:57PM ttys001 0:00.00 sleep 20
0 86754 51026 0 7:57PM ttys001 0:00.00 ps -ef
501 86755 51026 0 7:57PM ttys001 0:00.00 awk $3 ==51026우리는 수면 이 필요합니다.
$ ps -ef | awk -v ppid= $$ ' $3 == ppid && /slee[p]/
{print $2" -> "$5} '
86751 - > 7:57PM
86752 - > 7:57PM
86753 - > 7:57PM 솔루션은 추가하기 위해 새로운 조건이 필요합니다. 현재 레코드 / 슬리어에서 수면 패턴을 찾으십시오 /slee[p]/ .
트리거 된 조치는 PID 와 타임 스탬프 의 다섯 번째 $5 로 두 번째 필드 $2 인쇄하는 것입니다.
이 파일이 있습니다 :
$ cat ips.dat
IP BYTES
81.220.49.127 328
81.220.49.127 328
81.220.49.127 329
81.220.49.127 367
81.220.49.127 5302
81.226.10.238 328
81.227.128.93 84700 우리의 임무는 IP 당 얼마나 많은 바이트 수가 처리되는지를 계산하는 것입니다.
$ awk ' NR>1{ips[$1]+=$2}
END{for (ip in ips){print ip, ips[ip]}} ' ips.dat
81.220.49.127 6654
81.227.128.93 84700
81.226.10.238 328설명 할 많은 것들.
NR>1{ips[$1]+=$2} : 동작 ips[$1]+=$2 현재 레코드 번호가 1 NR>1 보다 큰 경우에만 실행됩니다. 헤더를 피하기 위해 필요합니다.
ips IP 값 ( $1 필드)에 의해 색인 된 배열이며, 각 키에 대해 두 번째 필드의 값에 축적 될 것입니다.
중요한 사실 에 주목하십시오. 어레이에 키가 존재하지 않으면 awk 구조 에 새로운 요소를 추가합니다. 그렇지 않으면 해당 키에 의해 지적 된 이전 값을 업데이트 할 것입니다 (예에서와 같이).
END 규칙은 인덱스와 값으로 배열을 반복하는 데 사용됩니다.
이 코드는 배열의 사용을 피하고 정렬 된 IPS 파일을 활용 한 순서를 보존하기 위해 완전히 다른 방식으로 다시 작성할 수 있습니다 .
awk ' NR==1{next}
lip && lip != $1{print lip,sum;sum=0}
{sum+=$2;lip=$1}
END{print lip,sum} ' ips.dat
81.220.49.127 6654
81.226.10.238 328
81.227.128.93 84700 NR==1{next} : 헤더를 우회합니다.
lip && lip != $1{print lip,sum;sum=0} : 여기서 우리는 var 이름의 lip ( last-IP )를 사용합니다. lip && lip != $1 lip 널이 아니고 첫 번째 필드와 같지 않을 때 (현재 IP를 보유 함) 트리거 된 동작은 lip 인쇄하고 마지막 IP의 총 바이트 양을 sum 것입니다. 그런 다음 sum=0 을 초기화합니다.
IP ( $1 )가 변경 될 때마다 우리는 이전의 통계 를 보여줍니다.
{sum+=$2;lip=$1} : 바이트 합계 sum+=$2 업데이트하고 현재 IP를 lip 에 할당하십시오 : lip=$1 . 그것은 우리의 기록 처리의 마지막 단계입니다.
END 블록은 보류중인 값을 인쇄하는 데 사용됩니다.
이 코드는 순서를 유지하지만 제 생각에는 복잡성이 크게 증가한 비용으로 발생합니다.
우리의 임무는 두 개의 추출 과 OUTPUT 과 END .
$ cat pat.dat
test -3
test -2
test -1
OUTPUT
top 2
bottom 1
left 0
right 0
page 66
END
test 1
test 2
test 3 이것은 패턴 매칭이 awk 에서 어떻게 작동하는지 설명하는 데 사용되는 전형적인 예 입니다.
$ awk ' /END/{flag=0}flag;/OUTPUT/{flag=1} ' pat.dat
top 2
bottom 1
left 0
right 0
page 66 flag 변수 값을 기준으로한다면, 시작 패턴 OUTPUT 발견되고 END 태그 에 도달하면 False ( 0 ) 가 될 때 ( 1 ).
추가 단계를 피하기 위해 로직 시퀀스를 따르는 경우 조치 순서가 매우 중요합니다 .
$ awk ' /OUTPUT/{flag=1}flag;/END/{flag=0} ' pat.dat
OUTPUT
top 2
bottom 1
left 0
right 0
page 66
END패턴 태그는 출력을 통해 표시됩니다.
이유 : OUTPUT 패턴이 발견 된 후 플래그가 활성화됩니다. 다음 조치는이 플래그에 따라 레코드가 인쇄됩니다.
우리는이 동작 이 플래그 활성화를 흐름의 마지막 단계 로 배치하는 것을 피할 수 있습니다.
이 파일을 가정 해 봅시다.
$ cat space.dat
10.80 kb
60.08 kb
35.40 kb
2.20 MB
1.10 MB
40.80 kb
3.15 MB
20.50 kb우리의 임무는 Mega Bytes 의 기록 총 중량을 계산하는 것입니다.
$ awk ' {total+= $1 / ($2=="kb" ? 1024: 1)}
END{print total} ' space.dat
6.61365그것이 어떻게 작동하는지 이해하려면 하나의 개념이 명확해야합니다. [Ternary] 연산자 (오래된 게시물의 주제).
total 제 3 달러짜리 $1 의 두 번째 $2 1 분할을 축적하는 데 사용되며, 이는 1024 $2 짜리 운영자 가 주어진 값을 보유 할 수 있습니다 kb
마지막으로, 우리는 END 블록에서 total 값을 인쇄합니다.
원본 출처 :
$ cat group.dat
string1
string2
string3
string4
string5
string6
string8우리의 임무는 다음과 같은 세 열의 블록 으로 레코드를 그룹화하는 것입니다.
string1 string2 string3
string4 string5 string6
string8 복잡해 보일 수 있지만 출력 필드 분리기를 OFS 하는 방법을 이해하면 훨씬 간단 해집니다 .
$ awk ' ORS = NR%3 ? FS : RS; END{print "n"} ' group.dat
string1 string2 string3
string4 string5 string6
string8 ORS 빈 문자, FS 기본값으로 설정하면 모든 출력이 한 줄이됩니다.
$ awk ' ORS=FS; END{print "n"} ' group.dat
string1 string2 string3 string4 string5 string6 string7 ORS = NR%3 ? FS : RS : 마지막으로 3 차 연산자 (직전에 설명)를 사용하여 현재 필드 수 NR 의 분할 결과 [Modulo] NR%3 결과를 3으로 평가합니다.
나머지가 참이면 ORS FS 됩니다. 빈 공간이됩니다. 그렇지 않으면 RS 기본값 이 n 됩니다.
생물 정보학 에서 [FASTA]는 텍스트 기반 파일 형식입니다.
다음 예제가 있습니다.
$ cat fasta.dat
> header1
CGCTCTCTCCATCTCTCTACCCTCTCCCTCTCTCTCGGATAGCTAGCTCTTCTTCCTCCT
TCCTCCGTTTGGATCAGACGAGAGGGTATGTAGTGGTGCACCACGAGTTGGTGAAGC
> header2
GGT
> header3
TTATGAT각 시퀀스의 총 길이 와 최종 이력서가 필요합니다.
다음과 같이 보일 것입니다.
> header1
117
> header2
3
> header3
7
3 sequences, total length 127 awk 이 보고 노력을 위한 완벽한 도구입니다.이 예를 위해 우리는 다음을 사용할 것입니다.
awk ' /^>/ { if (seqlen) {
print seqlen
}
print
seqtotal+=seqlen
seqlen=0
seq+=1
next
}
{
seqlen += length($0)
}
END{print seqlen
print seq" sequences, total length " seqtotal+seqlen
} ' fasta.dat
첫 번째 동작은 헤더 감지 /^>/ 에 연결되어 있으며 모든 헤더가 > 캐릭터와 함께 별이기 때문입니다.
seqlen 이 값을 null이 아닌 경우, 이전 시퀀스 길이를 유지하는 값은 새 헤더에 첨부 된 stdout 에 인쇄됩니다. seqtotal 이 업데이트되고 seqlen 다음 시퀀스를 제공하도록 초기화됩니다. 마지막으로, 우리는 next 에 추가로 기록 처리를 중단합니다.
두 번째 조치 {seqlen += length($0)} 총 레코드 길이를 합산하는 seqlen 업데이트하는 데 사용됩니다.
END 규칙 목적은 인쇄되지 않은 시퀀스와 총계를 보여주는 것입니다.
여기에서 트릭은 새 헤더를 찾았을 때 이전 시퀀스 길이를 인쇄하는 것입니다.
첫 번째 레코드를 처리 할 때 seqlen 값이 없으므로 시각화를 건너 뜁니다.
원천:
$ cat report.dat
snaps1: Counter: 4966
Opens: Counter: 357283
Instance: s.1.aps.userDatabase.mount275668.attributes
snaps1: Counter: 0
Opens: Counter: 357283
Instance: s.1.aps.userDatabase.test.attributes
snaps1: Counter: 5660
Opens: Counter: 37283
Instance: s.1.aps.userDatabase.mount275000.attributes 우리의 의무 : snaps 및 instance 시각화하는 보고서를 작성하지만 Snap First Counter Tag가 0보다 큰 경우에만 .
예상 출력 :
snaps1: Counter: 4966
Instance: s.1.aps.userDatabase.mount275668.attributes
snaps1: Counter: 5660
Instance: s.1.aps.userDatabase.mount275000.attributes우리는 패턴 과 깃발 주위에서 다시 놀고 있습니다.
awk ' {$1=$1}
/snaps1/ && $NF>0{print;f=1}
f && /Instance/ {print;f=0} ' report.dat 모든 레코드 에 대해 첫 번째 조치가 실행되면 OFS 3 의 현재 값을 사용하여 전체 레코드를 재건하도록 awk 합니다.
이 트릭 을 사용하면 다중 공간 분리기를 하나의 숯 으로 변환 할 수 있습니다.
이것을 보자 :
$ awk ' 1 ' text.dat
one two
three four$ awk ' $1=$1 ' text.dat
one two
three four 패턴이 발견되고 마지막 필드가 0 /snaps1/ && $NF>0 보다 큰 두 번째 동작이 트리거 됩니다.
awk 레코드를 인쇄하고 플래그 프린트에 진정한 값을 할당합니다 print;f=1 .
마지막 단계 : 플래그가 true 이고 줄 f && /Instance/ 의 인스턴스 패턴이있을 때, 선을 표시하고 플래그를 비활성화하십시오 : print;f=0 .
두 개의 아카이브를 가정 해 봅시다 :
$ cat join1.dat
3.5 22
5. 23
4.2 42
4.5 44$ cat join2.dat
3.5
3.7
5.
6.5 첫 번째 필드가 두 번째 필드에있는 경우 첫 번째 join1.dat join2.dat 레코드가 필요합니다.
출력은 다음과 같아야합니다.
3.5 22
5. 23물론 Unix Join 유틸리티를 사용할 수 있지만 첫 번째 파일을 정렬해야합니다.
$ join <( sort join1.dat ) join2.dat
3.5 22
5. 23 awk 에서 필요하지 않습니다 :
$ awk ' NR == FNR{a[$1];next}
$1 in a ' join2.dat join1.dat필터와 행동을 연구합시다.
NR == FNR : 레코드 번호 기록 파일 번호 와 동일한 레코드 번호는 awk 로 join2.dat 분석 된 첫 번째 파일을 처리하고 있음을 의미합니다.
쌍 액션 a[$1];next 첫 번째 필드에서 색인 된 배열에 새로운 공극 값을 추가하는 것입니다. next 진술은 레코드 프로세싱을 중단 하고 흐름을 다음 단계로 전달합니다.
두 번째 조치 의 경우 NR != FNR $1 in a 적 join1.dat 적용되고 join1.dat 에만 영향 을 미칩니다.
이것들은 Unix Classics 입니다.
$ cat /etc/group
dba:x:001:
netadmin:x:002:$ cat /etc/passwd
jd001:x:1032:001:Javier Diaz:/home/jd001:/bin/rbash
ag002:x:8050:002:Alejandro Gonzalez:/home/ag002:/bin/rbash
jp003:x:1000:001:Jose Perez:/home/jp003:/bin/bash
ms004:x:8051:002:Maria Saenz:/home/ms004:/bin/rbash
rc005:x:6550:002:Rosa Camacho:/home/rc005:/bin/rbash우리의 목표, 다음과 같은 보고서 :
d001:dba
ag002:netadmin
jp003:dba
ms004:netadmin
rc005:netadmin마지막 예제에서 공부 한 것처럼 여러 파일 흐름이 필요합니다.
$ awk -F : ' NR == FNR{g[$3]=$1;next}
$4 in g{print $1""FS""g[$4]} ' /etc/group /etc/passwd /etc/group 처리하기 위해 NR == FNR 비교를 반복 한 다음 ID $3 $1 g[$3]=$1 로 인덱스 된 그룹의 이름 을 저장하십시오. 마지막으로, 우리는 next 에 추가로 기록 처리를 중단합니다 .
두 번째 조건은 /etc/passwd 레코드 만 대상으로합니다. 네 번째 필드 $4 ( 그룹 ID )가 배열 $4 in g 그룹 ID g[$4] print $1""FS""g[$4] 의해 인덱스 된 배열에 의해 로그인 과 값을 인쇄 할 것입니다.
사용자 유틸리티 출력 예 :
$ users
negan rick bart klashxx klashxx ironman ironman ironman우리는 사용자 당 로그온을 계산할 것입니다.
$ users | awk ' {a[$1]++}
END{for (i in a){print i,a[i]}} ' RS= ' + '
rick 1
bart 1
ironman 3
negan 1
klashxx 2작업은 모든 레코드에 대해 수행됩니다.
a[$1]++ : 이것은 카운터 입니다. 각 사용자 에 대해 $1 대해 뾰족한 값을 증가시킵니다 (초기화 된 vars는 숫자 값이 0입니다).
END 블록 에서는 키에 의해 배열과 저장된 값을 반복하여 결과를 제시합니다.
일반적인 출력 :
$ uptime
11:08:51 up 121 days, 13:09, 10 users, load average: 9.12, 14.85, 20.84총 부하 평균 평균을 어떻게 얻을 수 있습니까?
$ uptime | awk ' {printf "Load average mean: %0.2fn",
($(NF-2)+$(NF-1)+$(NF))/3 } ' FS= ' (:|,) + '
Load average mean: 14.94여기에 새로운 기술이 있습니다.
우리는 [regex]를 필드 분리기 (:|,) + 로 사용하고 있으므로 FS 콜론 및 쉼표 와 0 이상의 빈 공간이 될 수 있습니다.
필요한 산술을 수행하려면 마지막 3 개의 필드 만 있으면 적절한 마스크 에 첨부 된 printf 사용합니다.
당신이 아직 여기 있다면 감사합니다 !!
내 관점에서 볼 때, awk 는 과소 평가 된 언어이며 많은 사랑이 필요합니다.
당신이 더 많은 것을 배고프면 댓글 섹션 벨로우즈에서 알려 주시면 내 임무를 마치기위한 두 번째 부분을 고려할 것입니다.
행복한 코딩!
[유닉스 쉘 인용에 대한 가이드] [인용 가이드]. ↩
[파이프 라인의 Wikipedia] [파이프]. ↩
FS 와 OFS 의 현재 값을 사용하여 awk 전체 레코드를 재건하도록 강요하는 것이 편리한 경우가 있습니다.
이를 위해, 우리는 겉보기에는 무해한 과제를 사용합니다. $1 = $1 ↩ ↩ 2
빠른 답변, 그것은 인쇄문을 사용하지 않는 바로 가기 일뿐 입니다.
조건이 일치 할 때 awk 에서는 기본 조치가 입력 라인을 인쇄하는 것입니다.
$ echo "test" |awk '1'
다음과 같습니다.
echo "test"|awk '1==1'
echo "test"|awk '{if (1==1){print}}'
1 항상 [참]이기 때문입니다. ↩