我有一个由存储库管理工具的输出生成的文本文件aptly
,其中列出了我发布的存储库,我需要从中提取信息。
文件格式如下:
Published repositories:
* test_repo_one/xenial [i386,amd64] publishes {main: [xenial-main_20190311]: Snapshot from mirror [xenial-main]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {multiverse: [xenial-multiverse_20190311]: Snapshot from mirror [xenial-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {restricted: [xenial-restricted_20190311]: Snapshot from mirror [xenial-restricted]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {universe: [xenial-universe_20190311]: Snapshot from mirror [xenial-universe]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}
* test_repo_one/xenial-security [i386,amd64] publishes {main: [xenial-security-main_20190311]: Snapshot from mirror [xenial-security-main]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {multiverse: [xenial-security-multiverse_20190311]: Snapshot from mirror [xenial-security-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {restricted: [xenial-security-restricted_20190311]: Snapshot from mirror [xenial-security-restricted]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {universe: [xenial-security-universe_20190311]: Snapshot from mirror [xenial-security-universe]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}
* test_repo_two/trusty [i386,amd64] publishes {main: [trusty-main_20190312]: Snapshot from mirror [trusty-main]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {multiverse: [trusty-multiverse_20190312]: Snapshot from mirror [trusty-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {restricted: [trusty-restricted_20190312]: Snapshot from mirror [trusty-restricted]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {universe: [trusty-universe_20190312]: Snapshot from mirror [trusty-universe]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}
...
输出的最后一行以新行结束。
“已发布的存储库:”行不是必需的。
对于以“*”开头的每一行,我需要删除无关信息,只留下快照名称。没有办法做到这一点aptly
。这些行中的第一行的所需输出是。
test_repo_one/xenial [xenial-main_20190311] [xenial-multiverse_20190311] [xenial-restricted_20190311] [xenial-universe_20190311]
方括号也不是必需的,因此保留或删除它们的解决方案很好。我更喜欢sed
orawk
解决方案,但任何有效的东西都会受到高度赞赏。
两个答案合二为一
我在这里发布了两个答案:
grep
,sed
以及cut
Bash 脚本在运行中的样子
我已关闭 gnome-terminal 换行以使输入和输出文件更易于阅读。
实际的 Bash 脚本
请记住使脚本可执行
chmod a+x script.sh
具有通用实用程序的单线
One-liners 在 Linux 社区中很受欢迎,并且在此问答中发布了一些出色
awk
的答案。perl
这是一个使用最有经验的命令行用户熟悉的常用实用程序的示例:grep ^" \*" aptfilein
- 该grep
命令选择包含搜索字符串的行。胡萝卜 (^
) 表示字符串必须从行首开始。反斜杠 (\
) 表示星号/splat (*
) 将按字面意思理解,而不是用作选择所有内容的通配符。总之,此命令选择以in filegrep
开头的所有行。*
aptfilein
sed
是一个“流编辑器”,它可以编辑进入的行并更改它们并将它们传递出去。这里有三个sed
变化's/ \* //;s/ /: /;s/^/ /'
。更改在引号 ('
) 之间并由分号 (;
) 分隔符划定(分隔)。他们在接下来的三点被打破。s/ \* //
- 搜索第一次出现*
并将其更改为空。这将擦除*
从每一行开始的。s/ /: /
- 搜索第一个空格并将其更改为冒号 (:
),后跟一个空格。这是将我们的第一个字段更改为键的必要条件。例如test_repo_one/xenial
变成test_repo_one/xenial:
.s/^/ /
- 告诉sed
在每行的开头插入一个空格。cut -d':' -f1,3,6,9,12 --output-delimiter=''
- 使用cut
命令选择关键字段#1、3、6、9和12。关键字段由冒号分隔,如参数-d':'
规定。通常输出字段的分隔符相同,但使用 --output-delimiter=''` 参数将其覆盖为 null。注意:单行比 bash 更快,后者在字符串处理方面更慢。
Perl 方法:
解释
perl -lne
: 逐行读取输入文件 (-n
),删除尾随换行符 ( ) 并运行每行-l
给出的脚本。还会为每个调用添加一个-e
换行符。-l
print
next unless /^\s*\*\s*(\S+)/;
: 找到 repo 的名称,因此第一行的非空白字符 (\S+
) 以 0 个或多个空白字符 (^\s*
) 开头,然后是*
(\*
),然后是 0 个或多个空白字符。之后最长的非空白区域就是我们想要的。如果此行与此正则表达式不匹配,next
则会将我们移至下一行。$n=$1
: 将上述匹配项((\S+)
括号中的$1
)捕获的内容保存为$n
.@k=(/\{.+?:\s*\[(.+?)\]/g)
: 找出我们有 a{
,任何其他字符,然后是 a:
,然后是空格和 a 的所有情况,[
并捕获介于 the[
和 the之间的任何内容]
。将所有匹配的字符串保存在数组中@k
。print "$n @k"
: 最后,从上面打印 repo 的名称、the$n
和数组@k
。如果您更喜欢包含方括号,您可以使用:
我的 awk 方法: