![使用 awk 定义“最小软件包集”的 bash 脚本](https://linux22.com/image/1069523/%E4%BD%BF%E7%94%A8%20awk%20%E5%AE%9A%E4%B9%89%E2%80%9C%E6%9C%80%E5%B0%8F%E8%BD%AF%E4%BB%B6%E5%8C%85%E9%9B%86%E2%80%9D%E7%9A%84%20bash%20%E8%84%9A%E6%9C%AC.png)
我想编写一个满足以下要求的脚本:
- 在输入中,获取可通过 获得的软件包列表
apt
。其中可能有一些软件包是由列表中的其他软件包自动安装的。 - 在输出中,提供相同的列表,但不提供依赖于列表中其他包的包。
换句话说,我想在 bash 中做什么用户 Francois G 在这个答案中
也许这样的东西已经存在,但有时我喜欢编写脚本来提高我的 bash 脚本编写能力,也是为了好玩。
在我的脑海里,我已经设计好了脚本,但是我遇到了一个技术问题。假设我有这种格式的依赖列表(就是这样的apt-rdepends
):
useless-line-1
useless-line-2
useless-line-3
item-1
fixed-string substring-1-1
fixed-string substring-1-2
fixed-string substring-1-3
item-2
fixed-string substring-2-1
fixed-string substring-2-2
item-3
item-4
fixed-string substring-4-1
fixed-string substring-4-2
fixed-string substring-4-3
fixed-string substring-4-4
我想提取与item-1
ie相关的段落:
fixed-string substring-1-1
fixed-string substring-1-2
fixed-string substring-1-3
我不是awk
专家,但我认为它可以满足我的目的。我无法“构建”正确的命令。由于可能item-2
不为人知,我尝试了:
# extract text between item-1 and the next line that starts without blank
$ awk '/item-1/,/^[A-Za-z0-9]/' deplist
item-1
但item-1
已经符合条件了^[A-Za-z0-9]
,所以不好。此外,我想从输出中排除item-1
和。item-2
提取该部分数据的最佳方法是什么?
答案1
你可以做一些“有状态的”事情,例如。
$ awk -v item='item-1' '$0 !~ /^[[:blank:]]/{p=0} $0 ~ "^" item {p=1} p' deplist
item-1
fixed-string substring-1-1
fixed-string substring-1-2
fixed-string substring-1-3
工作原理:
p=0
每当我们匹配到以水平空格以外的任何内容开头的行时设置(您可以^[A-Za-z0-9]
在这里使用稍微更具体的原始内容)如果
p=1
我们匹配所需的^item
随时打印
p==1
本质上“当我们匹配所需的项目时打开打印,当我们匹配任何其他项目时将其关闭”。
您需要一些额外的逻辑来跳过匹配的行:
$ awk -v item='item-1' '
$0 !~ /^[[:blank:]]/{p=0} {m = $0 ~ "^" item ? 1 : 0} m {p=1} p && !m
' deplist
fixed-string substring-1-1
fixed-string substring-1-2
fixed-string substring-1-3
在这里,我们执行相同的匹配,但将结果保存在变量中m
;然后设置p=1
何时m
为真(这部分与我们之前的相同);然后我们只打印何时p==1
和,m==0
即跳过实际匹配发生的行。