我是靠谱客的博主 敏感期待,这篇文章主要介绍shell实现文件分段提取,现在分享给大家,希望可以做个参考。

近期在问答模块看到一个小伙伴在问,如何从一个配置文件中提取出指定的几个片段。每个片段的起止行都有可识别的标识。

回到完问题后,决定把这个答题过程写得更清楚一点,以供后期查看和大家参考。

使用场景说明

平时工作中可能会遇到一些超大的配置文件。
很多时候我们只关注其中某些特别的部分,希望从中抽取出来单独分析。

案例解析

问题描述:

题主想从下面一个配置文件中提取每个Package: linux-headers-的配置内容(每段配置的起始行为:Package: linux-headers-,结束行为Build-Profiles: *)
并且把非目标行删除。

原始文件样式如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
. . . Package: linux-headers-abc . . . Build-Profiles: abc Package: linux-image-* . . . Build-Profiles: abc Package: linux-headers-def . . . Build-Profiles: def . . .

目标结果如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
Package: linux-headers-abc . . . Build-Profiles: abc Package: linux-headers-def . . . Build-Profiles: def

解题思路

复制代码
1
2
3
4
5
6
7
8
9
1-获取起始行:Package: linux-headers-的行号列表 2-获取结尾行:Build-Profiles的行号列表 3-用2层循环找1和2组成的起始行号对(比如起始行号为10,那就要找到第一个大于10的n行号,为其对应的截止行号)。 4-遍历上面的起始行号对,倒序删除。加入组成的对为5,10,20,25. 那么先删除25-最后 在删除10-20 再删除首行-5 这样剩下的就是要保留的

注意事项

复制代码
1
2
3
1.删除时记得一定要倒序删,正序前面的行号删掉后,后面的行号就变了,倒序删就没有这个问题 2.首行前面是否需要删除需要判断是否满足 第一个行号 > 1

脚本示例与说明

代码地址

我们一般情况都需要备份源文件,以防直接替换源文件出现问题有无法恢复源文件,所以今天我们给题主的需求中加一个备份(这一步属于建议)。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
filename=$1 # 操作前备份一下源文件 bak_filename=${filename}.bak cp ${filename} ${bak_filename} # 获取起始行集合 beginlines=$(grep -n 'Package: linux-headers-*' ${filename} | cut -d : -f 1) endlines=$(grep -n 'Build-Profiles:' ${filename} | cut -d : -f 1) # 获取起始行对 begin_end_arr=() for i in ${beginlines[*]}; do for j in ${endlines[*]}; do if [ $j -gt $i ]; then # 在结尾行集合中找到首个大于起始行号的行,并认定为对应结尾行号,一起加入到结果对中 begin_end_arr[${#begin_end_arr[*]}]=$i begin_end_arr[${#begin_end_arr[*]}]=$j echo begin_end_arr break; fi done done # 倒序遍历删除不匹配的行,一次遍历一对 #${#array[@]}获取数组长度用于循环 arr_length=${#begin_end_arr[@]} # 删除最后一行的下一行到文件文件尾部 lastline_num=${begin_end_arr[$((${arr_length}-1))]} sed -i $((${lastline_num}+1))',$d' ${filename} # 剔除出首尾行,中间按对删除 for ((i=$((${arr_length}-2));i>=1;i=i-2)) do begin=$((${begin_end_arr[i-1]}+1)) end=$((${begin_end_arr[i]}-1)) sed -i ${begin}','${end}'d' ${filename} done # 删除首行之前的全部行 firstline_num=${begin_end_arr[0]} [[ ${firstline_num} -gt 1 ]] && sed -i '1,'$((${firstline_num}-1))'d' ${filename} echo "done."

使用示例sh extract_part_lines.sh test.conf

最后

以上就是敏感期待最近收集整理的关于shell实现文件分段提取的全部内容,更多相关shell实现文件分段提取内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(74)

评论列表共有 0 条评论

立即
投稿
返回
顶部