링크 ux 기본 명령 소개 8: 텍스트 분석 awk

10077 단어 linuxshellbashawk
awk 모델 스 캔 과 처리 언어 로 데 이 터 를 분석 처리 할 때 매우 강력 한 도구 이다.
awk [options] 'pattern {action}' file...
awk 의 작업 과정 은 다음 과 같다. 줄 에 따라 입력 (표준 입력 또는 파일) 을 읽 고 패턴 pattern 에 맞 는 줄 에 대해 실행 action 한다.pattern 생략 할 때 모든 문자열 과 일치 하 는 것 을 표시 합 니 다.action 생략 할 때 집행 '{print}' 을 나타 낸다.그것들 은 동시에 생략 할 수 없다.각 줄 의 입력 은 awk 에 있어 하나의 기록 record 이 고 awk$0 을 사용 하여 현재 기록 을 참조 합 니 다.
[root@centos7 ~]# head -1 /etc/passwd | awk '{print $0}'
root:x:0:0:root:/root:/bin/bash

예 를 들 어 명령 head -1 /etc/passwdawk 의 입력 으로 하고 awk 은 생략 pattern, actionprint $0 현재 기록 을 인쇄 한 다 는 뜻 이다.각 기록 에 대해 서 는 awk 구분자 로 열 로 나 누고, 첫 번 째 열 용 $1 은 두 번 째 열 용 $2 은... 마지막 열 용 $NF 으로 표시 한다.
옵션 -F 은 출력 파일 /etc/passwd 의 첫 줄 첫 번 째 열 (사용자 이름) 과 마지막 열 (로그 인 셸) 과 같은 구분 자 를 지정 합 니 다.
[root@centos7 ~]# head -1 /etc/passwd | awk -F: '{print $1,$NF}'
root /bin/bash

구분자 가 지정 되 지 않 았 을 때 하나 이상 blank (공백 문자, 스페이스 바 나 TAB 키 로 생 성) 을 구분자 로 사용 합 니 다.출력 구분자 의 기본 값 은 빈 칸 입 니 다.출력 명령 ls -l * 의 결과 파일 크기 와 파일 이름:
[root@centos7 temp]# ls -l * | awk '{print $5,$NF}'
13 b.txt
58 c.txt
12 d.txt
0 e.txt
0 f.txt
24 test.sh
[root@centos7 temp]# 

임의의 열 을 필터 할 수 있 습 니 다:
[root@centos7 temp]# ls -l *|awk '$5>20 && $NF ~ /txt$/'
-rw-r--r-- 1 nobody nobody 58 11月 16 16:34 c.txt

그 중에서 $5>20 은 다섯 번 째 열의 값 이 20 보다 크다 는 것 을 나타 낸다.&& 논리 와$NF ~ /txt$/ 에서 ~ 는 일치 하 는 것 을 나타 내 고 기호 // 내 부 는 정규 표현 식 이다.여기 서 생략 action 했 습 니 다. 전체 awk 문 구 는 인쇄 파일 의 크기 가 20 바이트 이상 이 고 파일 이름 이 txt 로 끝 나 는 줄 을 표시 합 니 다.awkNR 으로 줄 번 호 를 표시 하 다.
[root@centos7 temp]# awk '/^root/ || NR==2' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@centos7 temp]#

예 에서 || 논리 적 또는 문 구 는 출력 파일 /etc/passwd 에서 루트 로 시작 하 는 줄 이나 두 번 째 줄 을 나타 낸다.
일부 상황 에서 awk 필 터 를 사용 하면 사용 grep 보다 ifconfig 의 출력 에서 네트워크 카드 이름과 그 에 대응 하 는 mtu 값 을 얻 을 수 있 습 니 다.
[root@idc-v-71253 ~]# ifconfig|awk '/^\S/{print $1"\t"$NF}'
ens32:  1500
ens33:  1500
lo:     65536
[root@idc-v-71253 ~]# 
#这里的正则表示不以空白字符开头的行,输出内容中使用\t进行了格式化。

이상 에서 말 한 NR, NF 등 은 모두 awk 의 내장 변수 입 니 다. 아래 부분 에 자주 사용 되 는 내장 변 수 를 보 여 줍 니 다.
$0          当前记录(这个变量中存放着整个行的内容)
$1~$n       当前记录的第n个字段,字段间由FS分隔
FS          输入字段分隔符 默认是空格或Tab
NF          当前记录中的字段个数,就是有多少列
NR          行号,从1开始,如果有多个文件话,这个值也不断累加。
FNR         输入文件行号
RS          输入的记录分隔符, 默认为换行符
OFS         输出字段分隔符, 默认也是空格
ORS         输出的记录分隔符,默认为换行符
FILENAME    当前输入文件的名字
awk 에서 사용자 정의 변 수 를 사용 할 수 있 습 니 다. 예 를 들 어 네트워크 카드 이름 을 변수 a 에 할당 한 다음 에 네트워크 카드 이름과 해당 하 는 RX bytes 값 을 출력 할 수 있 습 니 다.
[root@idc-v-71253 ~]# ifconfig|awk '/^\S/{a=$1}/RX p/{print a,$5}'
ens32: 999477100
ens33: 1663197120
lo: 0
awk 에는 두 개의 특수 한 pattern 이 있다. BEGINEND.입력 텍스트 와 일치 하지 않 습 니 다. BEGIN 에 대응 하 는 action 부분 은 코드 블록 으로 조합 되 어 입력 이 시작 되 기 전에 실 행 됩 니 다.END 에 대응 하 는 action 부분 을 하나의 코드 블록 으로 조합 하여 모든 입력 처리 가 끝 난 후에 실행 합 니 다.
#注意类似于C语言的赋值及print函数用法
[root@centos7 temp]# ls -l *|awk 'BEGIN{print "size name
---------"}$5>20{x+=$5;print $5,$NF}END{print "---------
total",x}' size name --------- 58 c.txt 24 test.sh --------- total 82 [root@centos7 temp]#
awk 배열 도 지원 합 니 다. 배열 의 색인 은 모두 문자열 (즉 관련 배열) 로 여 겨 집 니 다. for 출력 파일 /etc/passwd 의 각종 로그 인 셸 과 그 총 수량 을 순환 적 으로 옮 겨 다 닐 수 있 습 니 다.
#注意数组赋值及for循环遍历数组的写法
[root@centos7 temp]# awk -F ':' '{a[$NF]++}END{for(i in a) print i,a[i]}' /etc/passwd
/bin/sync 1
/bin/bash 2
/sbin/nologin 19
/sbin/halt 1
/sbin/shutdown 1
[root@centos7 temp]# 

물론 분기 문 도 있다.
#注意大括号是如何界定action块的
[root@centos7 temp]# netstat -antp|awk '{if($6=="LISTEN"){x++}else{y++}}END{print x,y}'
6 3
[root@centos7 temp]# 
if 사이 에 쉼표 로 구분 할 수 있 습 니 다. 첫 번 째 모드 부터 두 번 째 모드 와 일치 할 때 까지
[root@centos7 ~]# awk '/^root/,/^adm/' /etc/passwd       
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

또한 세 개의 조작 부호 pattern 를 지원 하여 pattern 1 이 일치 하 는 지 판단 하고 true 는 pattern 2 와 일치 하 며 false 는 pattern 3 와 일치 하 며 pattern 도 C 언어 와 유사 한 표현 식 일 수 있 습 니 다.파일 pattern1 ? pattern2 : pattern3 에서 UID 가 500 이상 인 로그 인 셸 이/bin/bash 인지 판단 하면 전체 줄 을 출력 합 니 다. 그렇지 않 으 면 UID 가 0 인 줄 을 출력 합 니 다.
#注意为避免混淆对目录分隔符进行了转义
[root@centos7 ~]# awk -F: '$3>500?/\/bin\/bash$/:$3==0 {print $0}' /etc/passwd         
root:x:0:0:root:/root:/bin/bash
learner:x:1000:1000::/home/learner:/bin/bash
#三目运算符也可以嵌套,例子略

옵션 /etc/passwd 은 file 에서 awk 명령 을 읽 는 것 을 표시 합 니 다.
#打印斐波那契数列前十项
[root@centos7 temp]# cat test.awk 
BEGIN{
    $1=1
    $2=1
    OFS=","
    for(i=3;i<=10;i++)
    {
        $i=$(i-2)+$(i-1)
    }
    print
}
[root@centos7 temp]# awk -f test.awk 
1,1,2,3,5,8,13,21,34,55
[root@centos7 temp]# 

옵션 -f file 지정 열 구분자
#多个字符作为分隔符时
[root@centos7 temp]# echo 1.2,3:4 5|awk -F '[., :]' '{print $2,$NF}'
2 5
[root@centos7 temp]#
#这里-F后单引号中的内容也是正则表达式

옵션 -F 변수 설정
#这里printf函数用法类似C语言同名函数
[root@centos7 ~]# awk -v n=5 'BEGIN{for(i=0;i
-v var=val 등 함수 에 서 는 리 셋 문자 print> 를 사용 하여 출력 을 파일 에 저장 하 는 것 도 지원 합 니 다.
#如按第一列(IP)分类拆分文件access.log,并保存至ip.txt文件中
[root@centos7 temp]# awk '{print > $1".txt"}' access.log 
[root@centos7 temp]# ls -l 172.20.71.*
-rw-r--r-- 1 root root 5297 11月 22 21:33 172.20.71.38.txt
-rw-r--r-- 1 root root 1236 11月 22 21:33 172.20.71.39.txt
-rw-r--r-- 1 root root 4533 11月 22 21:33 172.20.71.84.txt
-rw-r--r-- 1 root root 2328 11月 22 21:33 172.20.71.85.txt

내장 함수>> 문자열 길이 획득
[root@centos7 temp]# awk -F: '{if(length($1)>=16)print}' /etc/passwd 
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
[root@centos7 temp]#
length() 문자열 을 구분자 에 따라 구분 하고 배열 에 저장 합 니 다.
[root@centos7 temp]# head -1 /etc/passwd|awk '{split($0,arr,/:/);for(i=1;i<=length(arr);i++) print arr[i]}'
root
x
0
0
root
/root
/bin/bash
[root@centos7 temp]# 
split() 입력 (파이프, 다른 파일 또는 현재 파일 의 다음 줄 일 수 있 음) 에서 기록 을 얻 고 변 수 를 부여 하거나 환경 변 수 를 초기 화 합 니 다.
#从shell命令date中通过管道获得当前的小时数
[root@centos7 temp]# awk 'BEGIN{"date"|getline;split($5,arr,/:/);print arr[1]}'
09
#从文件中获取,此时会覆盖当前的$0。(注意逐行处理b.txt的同时也在逐行从c.txt中获得记录并覆盖$0,当getline先遇到eof时将输出空行)
[root@centos7 temp]# awk '{getline 
getline 역할 은 getline 과 유사 하 며, 다음 줄 을 읽 고 $0 을 덮어 씁 니 다. 차이 점 은 next 가 실 행 된 후 명령 을 실행 하지 않 고 다음 줄 을 읽 고 처음부터 다시 실행 하 는 것 입 니 다.
#跳过以a-s开头的行,统计行数,打印最终结果
[root@centos7 temp]# awk '/^[a-s]/{next}{count++}END{print count}' /etc/passwd
2
[root@centos7 temp]# 
#又如合并相同列的两个文件
[root@centos7 temp]# cat f.txt 
学号 分值
00001 80
00002 75
00003 90
[root@centos7 temp]# cat e.txt 
姓名 学号
张三 00001
李四 00002
王五 00003
[root@centos7 temp]# awk 'NR==FNR{a[$1]=$2;next}{print $0,a[$2]}' f.txt e.txt   
姓名 学号 分值
张三 00001 80
李四 00002 75
王五 00003 90
#这里当读第一个文件时NR==FNR成立,执行a[$1]=$2,然后next忽略后面的。读取第二个文件时,NR==FNR不成立,执行后面的打印命令
next 문자열 문자열 문자열 바 꾸 기 (생략 시 $0) 에서 정규 regex 와 일치 하 는 첫 번 째 하위 문자열 substr 가 나타 납 니 다.
[root@centos7 temp]# echo 178278 world|awk 'sub(/[0-9]+/,"hello")'
hello world
[root@centos7 temp]#
sub(regex,substr,string) 는 sub () 와 유사 하지만 첫 번 째 만 교체 하 는 것 이 아니 라 전체 국면 으로 교체 합 니 다.
[root@centos7 temp]# head -n5 /etc/passwd|awk '{gsub(/[0-9]+/,"----");print $0}'     
root:x:----:----:root:/root:/bin/bash
bin:x:----:----:bin:/bin:/sbin/nologin
daemon:x:----:----:daemon:/sbin:/sbin/nologin
adm:x:----:----:adm:/var/adm:/sbin/nologin
lp:x:----:----:lp:/var/spool/lpd:/sbin/nologin
gsub(regex,substr,string) 문자열 str 를 자 르 고 n 번 째 문자 부터 m 개 를 자 릅 니 다.하면, 만약, 만약...
[root@centos7 temp]# echo "hello,世界!"|awk '{print substr($0,8,1)}'
界
[root@centos7 temp]#
substr(str,n,m)tolower(str) 대소 문자 변환 표시
[root@centos7 temp]# echo "hello,世界!"|awk '{A=toupper($0);print A}'
HELLO,世界!
[root@centos7 temp]#
toupper(str) 셸 명령 cmd 를 실행 하고 실행 결 과 를 되 돌려 줍 니 다. 실행 성공 은 0 이 고 실 패 는 0 이 아 닙 니 다.
#此处if语句判断和C语言一致,0为false,非0为true
[root@centos7 temp]# awk 'BEGIN{if(!system("date>/dev/null"))print "success"}'
success
[root@centos7 temp]# 
system(cmd) 문자열 str 에서 정규 regex 와 일치 하 는 위 치 를 되 돌려 줍 니 다.
[root@centos7 temp]# awk 'BEGIN{A=match("abc.f.11.12.1.98",/[0-9]{1,3}\./);print A}'
7
[root@centos7 temp]# 
match(str,regex) 프로 그래 밍 언어 로 서 다양한 문 제 를 처리 할 수 있 고 심지어 응용 프로그램 을 작성 할 수 있 습 니 다. 그러나 명령 행 의 텍스트 분석, 보고서 생 성 등 이 더 자주 사용 되 는 부분 입 니 다. 이런 장면 에서 awk 잘 작 동 합 니 다.작업 중 에 텍스트 분석 에 대한 수요 가 자주 있 으 면 이 명령 의 용법 을 파악 하면 많은 시간 을 절약 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기