grep 跨行搜索(匹配)
grep 非常强大,可以在文件中搜索任意的字符串,通常的场景多是以行为单位进行检索,但若标识字符串与搜索内容不在一行怎么办? 例如下面的一个kubernetes部署文件,现在需要从该文件中取出部署名,也就是
metadata:
name: projecta-web-ms-deployment
中的name值。
apiVersion: apps/v1beta2 # for versions before 1.8.0 use apps/v1beta1
kind: Deployment
metadata:
name: projecta-web-ms-deployment
namespace: projecta-dev
labels:
app: projecta-web-ms
spec:
replicas: 1
selector:
matchLabels:
app: projecta-web-ms
template:
metadata:
labels:
app: projecta-web-ms
spec:
nodeSelector:
disktype: projectkdev
containers:
- name: projecta-web-ms
image: 192.168.1.8/projecta.io/projecta-web:1.5.0-SNAPSHOT
imagePullPolicy: Always
ports:
- containerPort: 8080
volumeMounts:
- name: v2
mountPath: /usr/projecta/logs
volumes:
- name: v2
hostPath:
path: /home/docker/data/tomcat/bpm/ms/logs
(1)首先取出带标识串的部分:
因为有多个name特征串,不能使用单行搜索,否则会返回多条数据。
命令: grep -Pzo "metadata:\s*\n name:.*$" deployment.yaml
说明:-P, --perl-regexp,使用Perl正则表达式; z,处理多行; o,只输出匹配部分。因为如果进行多行匹配,就没有换行作为匹配结束边界,会返回剩下的全部文本
结果:
metadata:
name: projecta-web-ms-deployment
(2)提取标识符所在行
命令:grep -Pzo "metadata:\s*\n name:.*$" deployment.yaml | grep name
结果:
name: pi6000-bpm-web-ms-deployment
(3)使用sed命令提取值
命令:grep -Pzo "metadata:\s*\n name:.*$" deployment.yaml | grep name | awk '{print $2}'
结果:
pi6000-bpm-web-ms-deployment
至此,就实现了我们最初的目标,提取出了跨行文本中的特征值。
(4)综合使用
若在脚本里执行,则需要将上述执行过程获得的值传到下面的脚本继续执行,这时,只需要定义一个变量保存提取值就可以了:
命令:
deploymentname=`grep -Pzo "metadata:\s*\n name:.*$" deployment.yaml | grep name | awk '{print $2}'`