当前位置:首页 > IT技术 > 系统服务 > 正文

【Shell】shell 日志处理(一行一行读文本-必须用while不能用for)shell 脚本 遍历文件 找出包含特定字符串的行数/行
2021-09-28 17:01:50

目录

​shell 获取结果中的第n列,第n行​

​AWK输出某几列​

​awk  遍历文件行处理​

​shell 脚本 遍历文件 找出包含特定字符串的行数/行​



​shell 获取结果中的第n列,第n行​

ls -l | awk '{print $5}' | sed -n '2p'

awk 是很实用的文本处理命令,print 到后带的是你要获取第几列,sed -n 是指定第几行。

AWK输出某几列

有这样一个文本,需要截取前5行

[root@SH]# cat test.txt 
2 3651415576 940761 0 0 0000000000000000
3 3532686312 939551 0 0 0000000000000000
4 3873453656 984285 0 0 0000000000000000
5 3884604640 970761 0 0 0000000000000000
6 2116906224 493295 0 0 0000000000000000
7 1760674752 480700 0 0 0000000000000000
8 0 0 29979808 6002 0000000000000000
10 0 0 3299944 1433 0000000000000000
11 0 0 2199434640 312565 0000000000000000

  • 可以awk '{print $1,$2,$3,$4,$5}
  • 另外一种实现方法awk '{NF-=2}1',这里的1换成别的数字也可以,NF-=2表示倒数第二列​

linux下统计某个进程的CPU占用和内存使用

#!/bin/bash
# while loop

CpuMemStat=""
datemk=""
while true
do
CpuMemStat=` ps aux |grep -i server |grep redis |grep -v py`
datemk=`date "+%Y-%m-%d %H:%M:%S"`
echo $datemk $CpuMemStat >> result.txt
#echo $datemk $CpuMemStat
sleep 20s
done

上面的遇到CpuMemStat结果是多行的就歇菜了,改成

#!/bin/bash
# while loop
CpuMemStat=""
datemk=""

CpuMemStat=`ps aux |sed -n '1p'|awk '{print $1,$2,$3,$4,$5}'`
datemk=`date "+%Y-%m-%d %H:%M:%S"`
echo $datemk $CpuMemStat >> result.txt

while true
do
#CpuMemStat=` ps aux |grep -i redis-server|awk '{print $1,$2,$3,$4,$5}'`
datemk=`date "+%Y-%m-%d %H:%M:%S"`


ps aux |grep -i redis-server|awk '{print $1,$2,$3,$4,$5}'|while read line
do
echo $line
echo $datemk $line >> result.txt
#echo $datemk $CpuMemStat
done

sleep 1s
done

(一行一行读,不能用for 必须用while,因为in操作符以任意空白字符作为分割, 而read line是以回车符作为分割。

注意 | 管道会起子进程,子进程内的变量无法传到外面,例如:

[liuhao@slave04 ~]$ cat test.sh 
#! /bin/sh

x=1
echo "adasd" | while read line
do
x=2
done
echo $x

运行结果是
[liuhao@slave04 ~]$ sh test.sh
1
原因

原来是因为管道|创建了新的子进程,而子进程是在独立的进程空间(Context)运行了. 需要跟父进程通信的话, 得使用进程间通信机制. 不是简单的变量问题。

有一文本文件如下,每行有两个字符串/空格分开。

$ cat list.txt 

Gly G

Ala A

Val V

Leu L

Ile I

Phe F



for line in `cat list.txt`

do

echo $line

done

得到结果如下:


Gly

G

Ala

A

Val

V

Leu

L

Ile

I

Phe

F


============

while read line

do 

echo $line

done list.txt


运行得到结果如下:


Gly G

Ala A

Val V

Leu L

Ile I

Phe F

awk  遍历文件行处理

awk基本语法如下:

awk 'BEGIN{//begin code }            pattern1{//pattern1 code}             pattern2{//pattern2 code}          END{//end code }'

BEGIN部分的代码,最先执行

然后循环从管道中读取的每行文本,如果匹配pattern1 ,则执行pattern1 code的代码,匹配pattern2,则执行pattern2 code代码

最后,执行END部分的代码end code

如下所示,分别求奇数行与偶数行的和:

$ seq 1 5

1

2

3

4

5

$ seq 1 5|awk 'BEGIN{print "odd","even"}    NR%2==1{odd+=$0}    NR%2==0{even+=$0}    END{print odd,even}'

odd even

9 6


实战:

info.txt

 -5        10.47839 root ssdpool                                        
-25        10.47839     rack rack.ssdpool                               
-28         3.49280         host rdma61.ssdpool                         
 18   ssd   0.87320             osd.18              up  1.00000 1.00000 
 21   ssd   0.87320             osd.21              up  1.00000 1.00000 
 24   ssd   0.87320             osd.24              up  1.00000 1.00000 
 28   ssd   0.87320             osd.28              up  1.00000 1.00000 
-31         3.49280         host rdma63.ssdpool                         
 20   ssd   0.87320             osd.20              up  1.00000 1.00000 
 22   ssd   0.87320             osd.22              up  1.00000 1.00000 
 25   ssd   0.87320             osd.25              up  1.00000 1.00000 
 27   ssd   0.87320             osd.27              up  1.00000 1.00000 
-34         3.49280         host rdma64.ssdpool                         
 19   ssd   0.87320             osd.19              up  1.00000 1.00000 
 23   ssd   0.87320             osd.23              up  1.00000 1.00000 
 26   ssd   0.87320             osd.26              up  1.00000 1.00000 
 29   ssd   0.87320             osd.29            down        0 1.00000 

写一个shell脚本 run.sh,我给它参数61(或者63或64), 它就读取host rdma61.ssdpool下面的行文字的第一个字段,并逐一输出log+字段,直至遇到下一个host rdma 停止。


如: run.sh 61


输出:


log18.txt

log21.txt

log24.txt

log28.txt


如: run.sh 63


log20.txt

log22.txt

log25.txt

log27.txt

脚本

awk -v flag=0 '
/host rdma'$1'/ {flag=1; next}
flag == 1 && /host rdma/ {flage=0; exit}
flag == 1 {print "log"$1".txt"}
' info.txt
 

-v flag=0 # 设置变量flag=0

/host rdma'$1'/ {flag=1; next}                   #匹配到host rdma'$1'执行flag=1; next,netx 表示不匹配本文本行后面的内容,直接跳到下一行文本

flag == 1 && /host rdma/ {flage=0; exit}  #flag == 1 且匹配到host rdma,则执行{flage=0; exit} ,exit 退出结束

flag == 1 {print "log"$1".txt"}                  #flag == 1 且匹配到host rdma,则执行print "log"$1".txt"​

shell 脚本 遍历文件 找出包含特定字符串的行数/行

#!/bin/bash

printf "************************************* "
a=0
while read line
do
[[ $line =~ "css" ]] && ((a++))
done < test.txt
echo $a

#!/bin/bash

ceph osd tree |& grep -E "ssd|ssdpool" > osd_nodes_id.txt

strA="rdma63.ssdpool"
while read -r line
do
echo ${line}
if [[ ${line} =~ ${strA} ]];
then
echo "包含"
fi
done < osd_nodes_id.txt

本文摘自 :https://blog.51cto.com/l

开通会员,享受整站包年服务立即开通 >