从 Linux 中的文件中剪切发行版本

从 Linux 中的文件中剪切发行版本

我有一个文件,其中包含操作系统软件包及其发行版本的列表。我只需要包名称,不需要发布版本。

如何使用 Linux 命令或任何脚本来实现此目的?

例子:

bind-export-libs-9.11.4-26.P2.el7_9.13
bind-export-libs-9.11.4-26.P2.el7_9.7
bind-libs-9.11.4-16.P2.el7
bind-libs-9.11.4-16.P2.el7_8.6
atk-2.28.1-1.el7
atk-2.28.1-2.el7
at-spi2-atk-2.26.2-1.el7
at-spi2-core-2.28.0-1.el7

在上面的列表中,根据发行版本存在重复的包条目。

如何只提取包名称?

答案1

我几乎确定您的列表是由rpm -qa类似的东西生成的,因此我给您一个命令,该命令仅显示包名称而不显示版本。这可以节省以后的大量工作:

rpm -qa --queryformat '%{NAME}\n' | sort

答案2

只需从倒数第二个破折号开始修剪所有内容即可。

使用sed

sed -r 's/-[^-]+-[^-]+$//' file.txt

基本上,RPM NVR 的通用格式是<name_possibly_containing_embedded_dashes_or_digits>-<version_never_containing_dashes>-<release_never_containing_dashes>.点或数字没有任何特殊含义,因此搜索它们永远无法正常进行。

在 的输出上运行它rpm -qa应该产生与 完全相同的列表rpm -qa --queryformat '%{NAME}\n',如建议的那样Artem 的回答。请注意,如果安装了单个软件包的多个版本或发行版,仍然会有重复的条目(前者是内核软件包或 gpg-pubkeys 的规范,后者是 i686/x86_64 库的典型)。sort -u如果您确实只想要唯一名称的列表,请运行结果。

# these two should produce the same output:
rpm -qa | sed -r 's/-[^-]+-[^-]+$//'
rpm -qa --queryformat '%{NAME}\n'

答案3

我觉得是TooTea的回答指出了正确的方法,而不是这个,出于参考原因,我仍然会保留它。


长话短说:RPM 文件名约定很复杂,并且如下所示,并不唯一。因此,在某些情况下,您实际上无法知道正确的包名称和版本控制是什么。不过,你可以尝试一下。

然而,由于这很复杂,所以不能简单地用 和 正则表达式来完成sed。不适合这项工作的工具。相反,使用 Redhat/Fedora 自己的工具。这个 Python 脚本应该会给你你想要的:

#!/usr/bin/env python3
from dnf.subject import Subject
from sys import stdin
from typing import Set
import hawkey


def filename_to_name_candidates(filename: str) -> Set[str]:
    subj = Subject(filename)
    return {
        candidate.name
        for candidate in subj.get_nevra_possibilities(forms=hawkey.FORM_NEVRA)
    }


names = set()

for line in stdin:
    try:
        names = names | filename_to_name_candidates(line)
    except:
        pass

for name in sorted(names):
    print(name)

将其保存在某处(例如,作为filename2packagename),使其可执行,(chmod 755 filename2packagename)。然后您可以通过管道输入文件名:

./filename2packagename < listofnames.txt

答案4

使用sed

$ sed -En 's/([^.]*)-.*/\1/;G;/^(.*)\n.*\n\1/d;H;P' input_file
bind-export-libs
bind-libs
atk
at-spi2-atk
at-spi2-core

相关内容