Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃苦瓜的猿
eagle-blog
提交
7e42ea1a
E
eagle-blog
项目概览
爱吃苦瓜的猿
/
eagle-blog
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
eagle-blog
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
7e42ea1a
编写于
8月 21, 2022
作者:
爱吃苦瓜的猿
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add extract_part_lines
上级
22f59365
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
207 addition
and
1 deletion
+207
-1
linux/README.md
linux/README.md
+3
-1
linux/extract_part_lines/README.md
linux/extract_part_lines/README.md
+134
-0
linux/extract_part_lines/extract_part_lines.sh
linux/extract_part_lines/extract_part_lines.sh
+46
-0
linux/extract_part_lines/test.conf
linux/extract_part_lines/test.conf
+24
-0
未找到文件。
linux/README.md
浏览文件 @
7e42ea1a
# linux
# linux
脚本工具片
## [linux启动停止脚本实现](linux/start_stop_script/README.md)
## [shell实现文件分段提取](linux/extract_part_lines/README.md)
linux/extract_part_lines/README.md
0 → 100644
浏览文件 @
7e42ea1a
# shell实现文件分段提取
近期在问答模块看到一个小伙伴在问,如何从一个配置文件中提取出指定的几个片段。每个片段的起止行都有可识别的标识。
回到完问题后,决定把这个答题过程写得更清楚一点,以供后期查看和大家参考。
## 使用场景说明
平时工作中可能会遇到一些超大的配置文件。
很多时候我们只关注其中某些特别的部分,希望从中抽取出来单独分析。
## 案例解析
### 问题描述:
题主想从下面一个配置文件中提取每个Package: linux-headers-
*的配置内容(每段配置的起始行为:Package: linux-headers-*
,结束行为Build-Profiles:
*
)
并且把非目标行删除。
原始文件样式如下:
```
.
.
.
Package: linux-headers-abc
.
.
.
Build-Profiles: abc
Package: linux-image-*
.
.
.
Build-Profiles: abc
Package: linux-headers-def
.
.
.
Build-Profiles: def
.
.
.
```
目标结果如下:
```
Package: linux-headers-abc
.
.
.
Build-Profiles: abc
Package: linux-headers-def
.
.
.
Build-Profiles: def
```
### 解题思路
```
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.首行前面是否需要删除需要判断是否满足 第一个行号 > 1
```
### 脚本示例与说明
[
代码地址
](
https://gitcode.net/eaglejava2015/eagle-blog/-/blob/master/linux/extract_part_lines/extract_part_lines.sh
)
我们一般情况都需要备份源文件,以防直接替换源文件出现问题有无法恢复源文件,所以今天我们给题主的需求中加一个备份(这一步属于建议)。
```
shell
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`
linux/extract_part_lines/extract_part_lines.sh
0 → 100644
浏览文件 @
7e42ea1a
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."
linux/extract_part_lines/test.conf
0 → 100644
浏览文件 @
7e42ea1a
.
.
.
Package
:
linux
-
headers
-
abc
.
.
.
Build
-
Profiles
:
abc
Package
:
linux
-
image
-*
.
.
.
Build
-
Profiles
:
abc
Package
:
linux
-
headers
-
def
.
.
.
Build
-
Profiles
:
def
.
.
.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录