mycpen

Mycpen

记录学习历程与受益知识
github
telegram
bilibili

29_Linux基礎-shellプログラミング-awk-sed

awk

入力区切り文字(-F、FS)、出力区切り文字(OFS)


awk でシェル変数を参照する

一. awk とシェル変数の交換の問題#

awk とシェル変数の交換の問題

1、-v オプションを使用する

2、ダブルクォーテーションを使用するが、awk 内部の $0 $1 などの $ 記号の前に \ でエスケープする必要がある

3、シングルクォーテーションを使用し、変数を囲み、その前に $ 記号を付けて再度変数の値を参照する。これは 2 回値を取得することに相当する

#例:-vオプションを使用する
[root@cPen_A ~]# sg="panjinhao"
[root@cPen_A ~]# echo $sg
panjinhao
[root@cPen_A ~]# echo|awk '{print $sg}'

[root@cPen_A ~]# echo|awk -v bsg=$sg '{print bsg}'
panjinhao
[root@cPen_A ~]# ls|awk -v bsg=$sg '{print bsg}'
panjinhao			#注:lsは複数行出力する
panjinhao
……
panjinhao

[root@cPen_A lianxi]# vim test2.sh 
awk -v var=$1 -F: '$1==var{print NR,$0}' /etc/passwd
[root@cPen_A lianxi]# bash test2.sh root
1 root:x:0:0:root:/root:/bin/bash
[root@cPen_A lianxi]# bash test2.sh sanchuang
21 sanchuang:x:1000:1000::/home/sanchuang:/bin/bash
#注:第1の$1は位置変数、第2の$1は第1のフィールド

#例:ダブルクォーテーションを使用するが、awk内部の$0 $1などの$記号の前に\でエスケープする必要がある
[root@cPen_A lianxi]# mv="zhangjie"
[root@cPen_A lianxi]# useradd zhangjie_123
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: "/^$mv/{print \$1,\$3}"
zhangjie_123 12358

#例:シングルクォーテーションを使用し、変数を囲み、その前に$記号を付けて再度変数の値を参照する。これは2回値を取得することに相当する
[root@cPen_A lianxi]# sg=3
[root@cPen_A lianxi]# awk -F: '/root/{print $1,$'$sg'}' /etc/passwd
root 0
operator 11

二。プロセス間通信の方法#

1、共有メモリ

2、セマフォ

3、シグナル

4、パイプ

5、キュー

6、ソケット


[root@cPen_A lianxi]# cat /etc/shadow
第2のフィールド:パスワードフィールド
*オペレーティングシステムに付属している、パスワードなし
!!ユーザーが作成した、パスワードなし
ヒント:パスワードフィールドが*、!!はパスワードが設定されていないことを示す;パスワードフィールドが空であることは、パスワードがクリアされたことを示す。
#例:パスワードが設定されていないユーザー
[root@cPen_A lianxi]# cat /etc/shadow|awk -F: 'BEGIN{i=0}length($2)<=2{print $1,"はパスワードが設定されていない";i++}END{print "合計で"i"人のユーザーがいる"}'

三. awk の組み込み関数#

awk の組み込み関数:

​ length()

​ int()

​ sqrt()

​ system()

文字列関数

​ sub()

​ index()

​ length()

​ split()

数値関数

yum install python3 python3 をインストールする

#例:0-1の間のランダム数を生成する
[root@cPen_A lianxi]# echo |awk '{print rand()}'
0.237788
#例:0-100の間のランダム数を生成する
[root@cPen_A lianxi]# echo |awk '{print rand()*100}'
23.7788
[root@cPen_A lianxi]# echo |awk '{print int(rand()*100)}'
23

四。フロー制御#

フロー制御:プロセス制御 control flow

for

while

case

if

if文
単一分岐
[root@cPen_A lianxi]# awk -F: '{if($1 ~ /\<...\>/)print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
[root@cPen_A lianxi]# awk -F: '$1 ~ /\<.{3}\>/{print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin

二重分岐
[root@cPen_A lianxi]# awk -F: '{if($1 ~ /\<...\>/)print $0;else print "条件を満たしていない"}' /etc/passwd
条件を満たしていない
bin:x:1:1:bin:/bin:/sbin/nologin

image-20221011220439733

#練習
/etc/passwd
$3はuid ユーザーの番号
もしユーザーの番号が0  --> 管理者
1~999  --> プログラムユーザー
1000より大きい --> 一般ユーザー
最後に、管理者、プログラムユーザー、一般ユーザーがそれぞれ何人いるかを統計する。
-----------------------------------------------------
[root@cPen_A ~]# awk -F: 'BEGIN{x=0;y=0;z=0}{if($3=="0") {print $1,"管理者";x++} else if($3>=1 && $3<=999) {print $1,"プログラムユーザー";y++} else  {print $1,"一般ユーザー";z++}}END{print "管理者"x,"プログラムユーザー"y,"一般ユーザー"z}' /etc/passwd
root 管理者
bin プログラムユーザー
……
管理者1 プログラムユーザー25 一般ユーザー40

五. awk の for ループ、配列#

image-20221011220532360

image-20221011220538243

image-20221011220551647

image-20221011220605574

image-20221011220614623


awk の難点:

  1. 正規表現

  2. if

  3. 組み込み関数

  4. 組み込み変数

  5. for、配列 array


六. sed#

sed とは?what --> テキストストリームエディタ
何に使うのか?where how --> テキストの変更と置換 --> modify and substitute

sed は正規表現をサポートする非対話型ストリーム編集ツール(stream editor)

​ スクリプト内でテキストを変更またはテキストを置換するための最良のツール

対話型:一問一答。例えば python3 でコマンドを入力する

image-20221011220732396

2 つのスペース
パターンスペース --> データを処理する場所 --> 1 行のデータを処理した後、パターンスペースはクリアされる
ホールドスペース --> データを一時的に保存する場所

パターンスペースをホールドスペースに移すコマンド:h、H

ホールドスペースをパターンスペースに移すコマンド:g、G

#注:パフォーマンス意識、sed はメモリ内で実行され、ディスクよりも速い

#注:容量意識


#例:-iオプション  ファイル内で直接変更し、画面には出力しない
[root@cPen_A lianxi]# sed -i 's/xiaomi/redmi/g' test.txt 
#例:パイプで渡す
[root@cPen_A lianxi]# cat chen |sed 's/xiaomi/redmi/g'

image-20221011220845338


[root@cPen_A lianxi]# cat -n /etc/passwd|head |tail -6
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6	sync:x:5:0:sync:/sbin:/bin/sync
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8	halt:x:7:0:halt:/sbin:/sbin/halt
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10	operator:x:11:0:operator:/root:/sbin/nologin
#例:-nオプション  一致した行を表示する(そうでなければすべて出力される)
[root@cPen_A lianxi]# cat -n /etc/passwd|sed -n '5,10p'
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6	sync:x:5:0:sync:/sbin:/bin/sync
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8	halt:x:7:0:halt:/sbin:/sbin/halt
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10	operator:x:11:0:operator:/root:/sbin/nologin

image-20221011220928234

sed の p コマンドの例#

= :行番号を出力する

pコマンド出力時:
連続した行
[root@localhost lianxi]# cat /etc/passwd|sed -n '1,5p'
不連続な行
[root@localhost lianxi]# cat /etc/passwd|sed -n '10p;20p'

例:sedのpコマンドの例
sed -n ‘行番号1,行番号2p’ 出力ファイル
[root@localhost lianxi]# cat /etc/passwd|sed -n '1,5p'			#注:連続して,で区切る
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost lianxi]# cat /etc/passwd|sed -n '=;1,5p'		#注:=;行番号を出力する
1
root:x:0:0:root:/root:/bin/bash
2
bin:x:1:1:bin:/bin:/sbin/nologin
3
daemon:x:2:2:daemon:/sbin:/sbin/nologin
4
adm:x:3:4:adm:/var/adm:/sbin/nologin
5
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6
7
……
14
[root@localhost lianxi]# cat -n /etc/passwd|sed -n '1,$p'		#注:$p最後の行
[root@localhost lianxi]# cat -n /etc/passwd|sed -n '5,+5p'		#注:第5行から5行追加
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6	sync:x:5:0:sync:/sbin:/bin/sync
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8	halt:x:7:0:halt:/sbin:/sbin/halt
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10	operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost lianxi]# cat -n /etc/passwd|sed -n '5,100!p'		#注:反転、1から4行を取得
     1	root:x:0:0:root:/root:/bin/bash
     2	bin:x:1:1:bin:/bin:/sbin/nologin
     3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4	adm:x:3:4:adm:/var/adm:/sbin/nologin
#例:ステップ値
	# cat -n /etc/passwd|sed -n '1~2p'
	# cat -n /etc/passwd|sed -n '2~2p'
[root@localhost lianxi]# cat -n /etc/passwd|sed -n '1~2p'	#注:奇数行、1から始めて2行ごとに
     1	root:x:0:0:root:/root:/bin/bash
     3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    11	games:x:12:100:games:/usr/games:/sbin/nologin
    13	nobody:x:99:99:Nobody:/:/sbin/nologin
    15	dbus:x:81:81:System message bus:/:/sbin/nologin
    17	sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    19	chrony:x:998:996::/var/lib/chrony:/sbin/nologin
    21	chenpeng:x:1001:1001::/home/chenpeng:/bin/bash
    23	nginx:x:996:994:Nginx web server:/var/lib/nginx:/sbin/nologin
[root@localhost lianxi]# cat -n /etc/passwd|sed -n '2~2p'		#注:偶数行
     2	bin:x:1:1:bin:/bin:/sbin/nologin
     4	adm:x:3:4:adm:/var/adm:/sbin/nologin
     6	sync:x:5:0:sync:/sbin:/bin/sync
     8	halt:x:7:0:halt:/sbin:/sbin/halt
    10	operator:x:11:0:operator:/root:/sbin/nologin
    12	ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    14	systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    16	polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    18	postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    20	mysql:x:1000:1000::/home/mysql:/sbin/nologin
    22	redis:x:997:995:Redis Database Server:/var/lib/redis:/sbin/nologin
#例:シェル変数をsedに渡す
#ダブルクォーテーション  推奨
[root@localhost lianxi]# num1=6
[root@localhost lianxi]# num2=10
[root@localhost lianxi]# cat -n /etc/passwd|sed -n "${num1},${num2}p"
     6	sync:x:5:0:sync:/sbin:/bin/sync
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8	halt:x:7:0:halt:/sbin:/sbin/halt
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10	operator:x:11:0:operator:/root:/sbin/nologin
#シングルクォーテーション
[root@localhost lianxi]# cat -n /etc/passwd|sed -n ''${num1},${num2}'p'
     6	sync:x:5:0:sync:/sbin:/bin/sync
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8	halt:x:7:0:halt:/sbin:/sbin/halt
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10	operator:x:11:0:operator:/root:/sbin/nologin

----------------------------------------------------------
#例:bashを含む行を表示する
[root@localhost lianxi]# cat /etc/passwd|sed -n '/bash/p'
root:x:0:0:root:/root:/bin/bash
chenpeng:x:1001:1001::/home/chenpeng:/bin/bash
[root@localhost lianxi]# cat /etc/passwd|egrep "bash"
root:x:0:0:root:/root:/bin/bash
chenpeng:x:1001:1001::/home/chenpeng:/bin/bash
[root@localhost lianxi]# cat /etc/passwd|awk '/bash/'
root:x:0:0:root:/root:/bin/bash
chenpeng:x:1001:1001::/home/chenpeng:/bin/bash

#例:#で始まる行を出力する
[root@localhost lianxi]# cat /etc/ssh/ssh_config |sed -n '/^#/p'
#例:#で始まらない行を出力する
[root@localhost lianxi]# cat /etc/ssh/ssh_config |sed -n '/^#/!p'
#例:#と!で始まらない行を表示する
[root@localhost lianxi]# cat /etc/ssh/ssh_config |sed -r -n '/^#|^$/!p'	#注:-rはより多くの正規表現をサポート
[root@localhost lianxi]# cat /etc/ssh/ssh_config |egrep -v '^#|^$'
#例:/で終わる行を表示する
[root@localhost lianxi]# df -h|egrep "/$"
/dev/mapper/centos-root   17G  9.9G  7.2G   58% /
[root@localhost lianxi]# df -h|sed -n '/\/$/p'
/dev/mapper/centos-root   17G  9.9G  7.2G   58% /

#例:a-Zで始まる行
[root@localhost lianxi]# cat /etc/passwd|sed -n '/^[a-Z]/p'
#例:a-Zで始まらない行
[root@localhost lianxi]# cat /etc/passwd|sed -n '/^[^a-Z]/p'

問題:nginxのaccess.logファイルから3月18日15:30:00 -- 16:48:10の時間帯内のすべてのアクセスログを切り取る

[root@cPen_A lianxi]# service firewalld stop	#注:firewalldサービスを即座に停止する
[root@cPen_A lianxi]# systemctl disable firewalld	#注:firewalldサービスを次回起動時に開始しないように設定する-->次回マシンを再起動する際に起動しない

[root@cPen_A nginx]# tail -f access.log		#注:最後の行を動的に監視する
192.168.0.17 - - [09/Jan/2021:16:36:03 +0800] "GET /favicon.ico HTTP/1.1" 404 3650 "http://192.168.0.118/" "Mozilla/5.0 (Linux; Android 10; PCT-AL10; HMSCore 5.1.0.300; GMSCore 20.26.14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 HuaweiBrowser/11.0.5.304 Mobile Safari/537.36" "-"
[root@cPen_A nginx]# pwd
/var/log/nginx				#注:nginxのログファイルのパス
[root@cPen_A nginx]# ls
access.log  access.log-20201202.gz  error.log  error.log-20201202.gz
#注:access.logはnginxのアクセスログファイルで、訪問したウェブサイトの情報を記録している
[root@cPen_A nginx]# cat access.log | awk -F'[()]' '{print $2}'|sort|uniq -c|sort -nr
     13 Windows NT 10.0; WOW64			#注:ソートして重複を削除し、降順にソートして数量を表示
      4 Linux; Android 10; PCT-AL10; HMSCore 5.1.0.300; GMSCore 20.26.14
--------------------------------------------------------------------------- 
[09/Jan/2021:16:32:46 +0800] --> 09/Jan/2021:16:32:46
[09/Jan/2021:16:33:07 +0800] --> 09/Jan/2021:16:32:46
#例:その時間帯のすべてのアクセスログを検索する
[root@cPen_A nginx]# cat access.log|sed -n '/09\/Jan\/2021:16:32:46/,/09\/Jan\/2021:16:33:07/p'
#例:正規表現の書き方
[root@cPen_A nginx]# cat access.log|sed -r -n '/09\/Jan\/2021:16:(3[789]|4[0-9]|5[01]):(0[1-9]|[1-5][0-9])/p'
#注:分の範囲は37~51 秒の範囲は01~59
#37~51
#37~39
#40~49
#50~51

#01~59
0[1-9]|[1-5][0-9]

sed の d コマンドの例#

sedのdコマンドの例
削除操作は行番号と一致パターンに基づいて行うことができる
#例:denghuiを含む行を削除する
[root@cPen_A nginx]# cat /etc/passwd|sed '/denghui/d'
#例:-iオプションで元のファイルを直接変更し、redmiを含む行を削除する
[root@cPen_A lianxi]# sed -i '/redmi/d' test.txt 
#例:行に基づいて削除する
[root@cPen_A lianxi]# sed -i '2d' test.txt 	#注:第2行を削除する
sedの検索方法:
	1、行番号に基づいて
	2、一致パターンに基づいて --> 正規表現=文字+特殊記号
	3、文字列に基づいて

#例:第4行の後にhuaweiを追加する
[root@cPen_A lianxi]# sed -i '4a huawei' test.txt 
#例:第4行の前にappleを挿入する
[root@cPen_A lianxi]# sed -i '4i apple' test.txt 
#例:VIVOの行の前にOPPOを挿入する
[root@cPen_A lianxi]# sed -i '/VIVO/i OPPO' test.txt 
#例:VIVOの行の後にAPPLEを追加する。&は前のすべてを示す
[root@cPen_A lianxi]# sed -i 's/VIVO/& APPLE/' test.txt 
#例:すべてのhuaweiをsanchuangに置き換える
[root@cPen_A lianxi]# sed -i 's/huawei/sanchuang/g' test.txt 
sedのコマンド:
	p
	d
	a
	i
	s
	c
	r
	w
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。