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

투티에서 나온 것 같아요답변이 접근 방식 대신 올바른 접근 방식을 지적했는데, 이는 참고용으로 계속 유지하겠습니다.


간단히 말해서, 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

관련 정보