각 줄에 있는 순서가 지정된 하위 문자열을 기준으로 파일을 안정적으로 정렬합니다.

각 줄에 있는 순서가 지정된 하위 문자열을 기준으로 파일을 안정적으로 정렬합니다.

스크립트를 사용하여 처리 중인 음원 목록이 있습니다. 예는 다음과 같습니다:

alsa_input.usb-AVEO_Technology_Corp._USB2.0_Camera-02-Camera.analog-mono
alsa_input.pci-0000_00_14.2.analog-stereo
alsa_input.usb-Plantronics_Plantronics_GameCom_780-00-P780.analog-stereo

어떤 위치에서든 하위 문자열을 기준으로 정렬하고 싶습니다.

예를 들어, USB 장치를 먼저 배치하고 싶습니다 sort --by usb file.txt(순서를 유지하면서).

alsa_input.usb-AVEO_Technology_Corp._USB2.0_Camera-02-Camera.analog-mono
alsa_input.usb-Plantronics_Plantronics_GameCom_780-00-P780.analog-stereo
alsa_input.pci-0000_00_14.2.analog-stereo

보다 세분화된 우선순위를 얻기 위해 여러 하위 문자열을 지정할 수 있기를 원합니다. 따라서 sort --by Platronics --by usb file.txt"Platronics"가 포함된 줄이 먼저 배치되고, "usb"가 포함된 줄, 나머지가 차례로 배치됩니다.

이 작업을 수행하는 데 사용할 수 있는 명령줄 유틸리티가 있습니까?

답변1

점수 시스템을 원하는 것 같습니다. 출력에서 해당 줄을 얼마나 자주 보고 싶은지 나타내는 점수를 각 줄에 할당하는 스크립트를 작성하세요.  awk그 직업에 딱 맞는 것 같습니다. 귀하의 예를 들어:

#!/bin/sh
awk '{score=0}
    /usb/ {score=1}
    /Plantronics/ {score=2}
    {print score, NR, $0}' "$@"

기본적으로 이는 각 행에 점수 0을 할당한 다음 행에 포함된 경우 1로 덮어쓰고 usb 행에 포함된 경우 2 로 덮어씁니다 Plantronics. usb및 문을 이 순서대로 배치했으므로 Plantronics한 줄에 두 개의 문자열이 포함되어 있으면 최종 값은 2가 됩니다. 그 다음에

./score file.txt | sort -k1nr -k2n | cut -d" " -f3-

( score스크립트 이름은 어디에 있습니까?)  sort -k1nr첫 번째 필드(점수)를 기준으로 정렬을 의미하며, 이를 숫자로 처리하고 더 높은 값을 먼저 정렬합니다(스크립트가 score가장 관심 있는 행에 높은 점수를 할당하기 때문입니다).  -k2n즉, 첫 번째 필드에 동일한 값이 있는 행의 경우 두 번째 필드를 기준으로 일반 오름차순으로 정렬됩니다. 두 번째 필드는 NR레코드 번호(라인 번호라고도 함)입니다. 이렇게 하면 점수가 동일한 행(예: usb포함되었지만 포함되지 않은 행 Plantronics)이 원래 순서대로 표시됩니다. 이에 대해 신경 쓰지 않는다면 NR,명령문에서 제거하고 명령에서 제거한 후 print다음으로 변경하십시오. (실제로 이러한 순서는 기본적으로 유지될 수 있으므로 전혀 필요하지 않을 수도 있습니다.) 물론 이렇게 하면 스크립트가 데이터 앞에 추가하는 숫자가 제거됩니다.-k2nsort-f3--f2-sortcut -d" " -f3-score

이것이 어떻게 작동하는지 완전히 이해하지 못한다면 다음을 실행해 보십시오.

./score file.txt

그리고

./score file.txt | sort -k1nr -k2n

이 접근 방식은 매우 유연합니다. 예를 들어 위의 코드는 다음을 생성합니다.

  • 다음을 포함하는 모든 Plantronics
  • usb포함 하지만 포함하지 않는 모든 Plantronics행 및
  • 위의 내용을 포함하지 않는 모든 라인,

각 그룹은 입력 파일의 발생 순서에 따라 정렬됩니다. 그러나 score스크립트를 다음과 같이 변경하면,

#!/bin/sh
awk '{score=0}
    /usb/ {score+=1}
    /Plantronics/ {score+=2}
    {print score, NR, $0}' "$@"

두 개의 문자열을 포함하는 선에 3개의 점을 할당할 수 있으므로 이제

  • 다음을 포함하는 모든 행Plantronics 그리고 usb, 이어서
  • Plantronics다음을 포함 하지만 포함하지 않는 모든 usb행 뒤에
  • 다음 을 포함 usb하지만 포함하지 않는 모든 행Plantronics
  • 위의 내용을 포함하지 않는 모든 줄.

답변2

with sqliteORDER BY절:

$sqlite3 <<\EOT
CREATE TABLE file(line);
.import file.txt file
SELECT * FROM file
ORDER BY
CASE
    WHEN line LIKE '%USB%' THEN 0
    WHEN line LIKE '%Realtek%' THEN 1
    ELSE 3
END;
EOT
00:10.0 USB controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller (rev 81)
00:10.1 USB controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller (rev 81)
00:10.2 USB controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller (rev 81)
00:10.3 USB controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller (rev 81)
00:10.4 USB controller: VIA Technologies, Inc. USB 2.0 (rev 86)
00:05.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (rev 10)
00:06.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (rev 10)
00:07.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (rev 10)
00:00.0 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro Host Bridge
00:00.1 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro Host Bridge
00:00.2 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro Host Bridge
00:00.3 Host bridge: VIA Technologies, Inc. PT890 Host Bridge
00:00.4 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro Host Bridge
00:00.7 Host bridge: VIA Technologies, Inc. CN700/VN800/P4M800CE/Pro Host Bridge
00:01.0 PCI bridge: VIA Technologies, Inc. VT8237/VX700 PCI Bridge
00:0f.0 IDE interface: VIA Technologies, Inc. VIA VT6420 SATA RAID Controller (rev 80)
00:0f.1 IDE interface: VIA Technologies, Inc. VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (rev 06)
00:11.0 ISA bridge: VIA Technologies, Inc. VT8237 ISA bridge [KT600/K8T800/K8T890 South]
01:00.0 VGA compatible controller: VIA Technologies, Inc. CN700/P4M800 Pro/P4M800 CE/VN800 Graphics [S3 UniChrome Pro] (rev 01)

답변3

당신이 하고 있는 일은 실제로 분류하는 것이 아니라 선택하는 것입니다. 따라서 해야 할 일은 먼저 "Platronics"가 포함된 모든 행을 선택한 다음 "usb" 등이 포함된 모든 행을 선택하고 마지막으로 일치하지 않는 모든 행을 선택하는 것입니다.

이 작업을 한 번에 수행하는 명령은 모르지만 python이를 사용하여 원하는 작업을 수행하는 작은 스크립트를 작성할 수 있습니다.

import sys

substrings = sys.argv[1:]
lines = sys.stdin.readlines()

# for each substring, print matching lines
for substring in substrings:
    i=0
    while i<len(lines):
        if substring in lines[i]:
            # match: print and remove
            sys.stdout.write(lines[i])
            del lines[i]
        else:
            # no match: try next line
            i += 1

# finally, print all lines that weren't matched
for line in lines:
    sys.stdout.write(line)

그것은 당신이 원하는 것을 수행합니다:

$ lspci | python substrings.py "USB controller" "PCI bridge"
00:1a.0 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #4 (rev 02)
00:1a.1 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #5 (rev 02)
00:1a.2 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #6 (rev 02)
00:1a.7 USB controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #2 (rev 02)
00:1d.0 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #1 (rev 02)
00:1d.1 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #2 (rev 02)
00:1d.2 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #3 (rev 02)
00:1d.7 USB controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #1 (rev 02)
00:1c.0 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 1 (rev 02)
00:1c.1 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 2 (rev 02)
00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev 92)
00:00.0 Host bridge: Intel Corporation 82Q33 Express DRAM Controller (rev 02)
00:02.0 VGA compatible controller: Intel Corporation 82Q33 Express Integrated Graphics Controller (rev 02)
00:02.1 Display controller: Intel Corporation 82Q33 Express Integrated Graphics Controller (rev 02)
00:03.0 Communication controller: Intel Corporation 82Q33 Express MEI Controller (rev 02)
00:19.0 Ethernet controller: Intel Corporation 82566DM-2 Gigabit Network Connection (rev 02)
00:1b.0 Audio device: Intel Corporation 82801I (ICH9 Family) HD Audio Controller (rev 02)
00:1f.0 ISA bridge: Intel Corporation 82801IB (ICH9) LPC Interface Controller (rev 02)
00:1f.2 IDE interface: Intel Corporation 82801IB (ICH9) 2 port SATA Controller [IDE mode] (rev 02)
00:1f.5 IDE interface: Intel Corporation 82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (rev 02)

답변4

고양이 파일:

22
z
there's
a
moose
loose
in
the
hoose

예를 들어. 인수를 다음으로 설정하십시오. loose moose- 스크립트로 읽기 "$@" 원하는 만큼 사용할 수 있습니다.

by=( "$@" )
nl file | sed -nf <(for ((i=0;i<${#by[@]};i++)) ;do 
                      echo "s/.*${by[i]}.*/$i\t&/; t p"
                    done; echo "s/^/$i\t&/; :p p") |
            sort -nk1 -nk2 | cut -f3-

산출:

loose
moose
22
z
there's
a
in
the
hoose

관련 정보