목록을 숫자순으로 정렬

목록을 숫자순으로 정렬

다음 구조의 텍스트 목록이 있습니다(각 항목의 모든 줄은 탭 공백으로 시작하고 줄 사이에 빈 줄이 없으며 항목 사이에 하나의 빈 줄이 있습니다).

  292G.- La Ilíada (tomo I) ; Collection one (volume 3) ; Homer ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Homero/Iliada.pdf
  - I have to download more ancient greek texts.
  - Another note line.

  293G.- El Ingenioso Hidalgo "Don Quijote" De La Mancha ; Collection one (volume 1) ; Miguel de Cervantes ; http://www.daemcopiapo.cl/Biblioteca/Archivos/7_6253.pdf
  - Masterpiece.

  294G.- Crimen y castigo ; Collection one (volume 4) ; Fiódor Dostoyevski ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Fedor%20Dostoiewski/Crimen%20y%20castigo.pdf
  - Russian masterpiece.

  295G.- La isla del tesoro ; Collection one (volume 2) ; Robert Louis Stevenson ; https://www.biblioteca.org.ar/libros/130864.pdf
  - I read this one as a kid.

292G 위치에서 시작하여 100권이 넘는 컬렉션이 계속됩니다. 나는 이 100권을 권 번호(두 번째 필드에서 찾을 수 있음)별로 정렬하고 싶습니다. 예상되는 출력은 다음과 같습니다.

  292G.- El Ingenioso Hidalgo "Don Quijote" De La Mancha ; Collection one (volume 1) ; Miguel de Cervantes ; http://www.daemcopiapo.cl/Biblioteca/Archivos/7_6253.pdf
  - Masterpiece.

  293G.- La isla del tesoro ; Collection one (volume 2) ; Robert Louis Stevenson ; https://www.biblioteca.org.ar/libros/130864.pdf
  - I read this one as a kid.

  294G.- La Ilíada (tomo I) ; Collection one (volume 3) ; Homer ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Homero/Iliada.pdf
  - I have to download more ancient greek texts.
  - Another note line.

  295G.- Crimen y castigo ; Collection one (volume 4) ; Fiódor Dostoyevski ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Fedor%20Dostoiewski/Crimen%20y%20castigo.pdf
  - Russian masterpiece.

"헤더에는 , (, ), 와 같은 문자와 문자열이 포함될 수 있지만 포함 되지는 않습니다 ;(구분자 역할만 함). sort여기에 답이 있다고 생각 하지만 그것은 내 멍청한 능력을 넘어서는 것입니다.

답변1

명시적인 언어 요구 사항을 지정하지 않았으므로 이는 Python 3.8의 더러운 솔루션입니다. 다른 사람들이 더 나은 방법을 생각해낼 수 있다고 확신하지만 이것만으로도 충분합니다.

이 코드는 텍스트가 현재 디렉터리의 list.txt라는 파일에 있다고 가정하고 new-list.txt라는 새 파일을 생성합니다.

또한 "-La isla del tesoro"에서 누락된 공백을 처리하지 않습니다.

import re

booklist = []
bookcount = 0
entry = ''
line_numbers = []

# Find and return the volume number for a book
def get_volnum(book):
        volstring = ''
        volstring = re.search('\\(volume (\d+)\\)', book)
        volnum = volstring.group(1)
        return volnum

# Read file and put in doc variable
doc = open('list.txt', 'r').readlines()

# Group each book in a single string and append in a booklist
for line in doc:
    # if line begins with three decimals followed by 'G.', put line in a new entry. 
    if re.match("(\d\d\d)G.*", line): 
        #read the line number and append to a list
        line_numbers.append(line.split('G.')[0])
        # Add previous entry to booklist (without the three decimals and G.)
        if bookcount > 0:
            booklist.append(entry.split('G.')[1])  

        entry = line
        bookcount +=1
    # If line begins with a '- ', concatenate the line into the current entry.
    if line.startswith('- '):
        entry += line

#Append last line
booklist.append(entry.split('G.')[1])  
# Make a list (booktable) that contains [volnum, book]
booktable = []
[booktable.append([get_volnum(book), book]) for book in booklist]

# Sort that list by volnum (index 0 of each list item of booktable)
booktable.sort(key=lambda x: int(x[0]))

line_numbers.sort()

# Write result to file
f = open("new-list.txt", "w")
for b in booktable:
    f.write(line_numbers.pop(0) + 'G.' + b[1])
    f.write('\n')

f.close()

답변2

이것은 (세 번째 인수가 , 및 제목에 , 또는 가 포함 설정된문자열match()된 GNU awk를 사용하면 정렬되지 않은 주변 섹션 내의 원래 위치에 정렬된 섹션을 출력합니다.gensub()sorted_inFPAT;()(volume <N>)

$ cat tst.awk
BEGIN {
    RS = ""
    ORS = "\n\n"
    FPAT = "[^;]*(\"[^\"]*\")*[^;]*"
    tgtColl = "one"
    begSeqNr = 292
    maxSeqs = 100
}
match($2,/Collection (.*) \(volume ([0-9]+))/,a) {
    coll  = a[1]
    volNr = a[2]
    seqNr = $1+0
}
(coll == tgtColl) && (seqNr >= begSeqNr) && (++seqCnt <= maxSeqs) {
    vols[volNr] = $0
    next
}
{
    prtVols()
    print
}
END { prtVols() }

function prtVols(       volNr, seqNr, vol) {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    seqNr = begSeqNr
    for (volNr in vols) {
        vol = vols[volNr]
        sub(/[0-9]+/,seqNr++,vol)
        print vol
    }
    delete vols
}

예를 들어, 이 입력이 질문의 화창한 날 사례에서 수정되어 몇 가지 유용한 테스트 사례를 추가한다고 가정합니다.

$ cat file
  100G.- some earlier collection ; Collection zero (volume 1) ; Robert Louis Stevenson ; https://www.biblioteca.org.ar/libros/130864.pdf
  - TEST earlier collection ID

  200G.- right collection, too early sequence number; Collection one (volume 6) ; Homer ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Homero/Iliada.pdf
  - TEST earlier sequence number

  292G.- La Ilíada ; Collection one (volume 3) ; Homer ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Homero/Iliada.pdf
  - I have to download more ancient greek texts.
  - Another note line.

  293G.- El Quijote ; Collection one (volume 1) ; Miguel de Cervantes ; http://www.daemcopiapo.cl/Biblioteca/Archivos/7_6253.pdf
  - Masterpiece.

  294G.- Crimen y castigo ; Collection one (volume 4) ; Fiódor Dostoyevski ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Fedor%20Dostoiewski/Crimen%20y%20castigo.pdf
  - Russian masterpiece.

  295G.- "Kill Bill; Bury Him (volume 2)" ; Collection one (volume 5) ; Tarantino ; https://www.biblioteca.org.ar/libros/130864.pdf
  - TEST quoted title with sparator chars and target string

  296G.- La isla del tesoro ; Collection one (volume 2) ; Robert Louis Stevenson ; https://www.biblioteca.org.ar/libros/130864.pdf
  - I read this one as a kid.

  300G.- some later collection ; Collection twenty-three (volume 2) ; Robert Louis Stevenson ; https://www.biblioteca.org.ar/libros/130864.pdf
  - TEST later collecion ID

다음과 같이 출력됩니다.

$ awk -f tst.awk file
  100G.- some earlier collection ; Collection zero (volume 1) ; Robert Louis Stevenson ; https://www.biblioteca.org.ar/libros/130864.pdf
  - TEST earlier collection ID

  200G.- right collection, too early sequence number; Collection one (volume 6) ; Homer ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Homero/Iliada.pdf
  - TEST earlier sequence number

  292G.- El Quijote ; Collection one (volume 1) ; Miguel de Cervantes ; http://www.daemcopiapo.cl/Biblioteca/Archivos/7_6253.pdf
  - Masterpiece.

  293G.- La isla del tesoro ; Collection one (volume 2) ; Robert Louis Stevenson ; https://www.biblioteca.org.ar/libros/130864.pdf
  - I read this one as a kid.

  294G.- La Ilíada ; Collection one (volume 3) ; Homer ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Homero/Iliada.pdf
  - I have to download more ancient greek texts.
  - Another note line.

  295G.- Crimen y castigo ; Collection one (volume 4) ; Fiódor Dostoyevski ; http://www.ataun.eus/BIBLIOTECAGRATUITA/Cl%C3%A1sicos%20en%20Espa%C3%B1ol/Fedor%20Dostoiewski/Crimen%20y%20castigo.pdf
  - Russian masterpiece.

  296G.- "Kill Bill; Bury Him (volume 2)" ; Collection one (volume 5) ; Tarantino ; https://www.biblioteca.org.ar/libros/130864.pdf
  - TEST quoted title with sparator chars and target string

  300G.- some later collection ; Collection twenty-three (volume 2) ; Robert Louis Stevenson ; https://www.biblioteca.org.ar/libros/130864.pdf
  - TEST later collecion ID

필드 구분 기호이므로 ;제목에 나타나는 모든 항목은 단독으로 Kill Bill";" Bury Him또는 인용된 전체 제목의 일부로(위의 예에서와 같이) 큰따옴표 안에 있어야 하며, 제목에 다른 문자가 있거나 문자열 중 아무 것도 필요하지 않습니다. 특별한 취급.

one이것은 매우 사소한 조정이며 실제로 모든 세트를 원하고 begSeqNr다음 과 같습니다. for 에 대한 텍스트 없이 100개만, seqCnt주변 세트/시퀀스를 인쇄하지 않으려면 독립형 print명령문을 제거하면 됩니다.

답변3

통해 awk그리고암소 비슷한 일종의 영양-특징(!)는 배열 순회를 정의합니다. 참고: 전체 파일이 한 번에 RAM에 저장되는데 "볼륨이 100개 이상"이라고 하셨으므로 파일이 그다지 크지 않다고 가정합니다.

아이디어는

  1. 빈 줄로 레코드 구분(탭이 없다고 가정하고 한 줄에 두 개의 줄 바꿈)
  2. 필드 구분 기호로 괄호를 사용합니다. 볼륨 번호를 인덱스 식별자로 사용하여 행을 배열에 넣습니다. 따라서 숫자를 결합해야합니다.sub
  3. "볼륨 X" 색인을 기준으로 출력 정렬
  4. 정렬된 방식으로 각 항목의 번호를 바꾸십시오(293G 등).

스크립트:

BEGIN { RS="" ; ORS="\n\n" ; FS="[()]" }

{id=$2 ; sub(/volume /,"",id) ; vol[id]=$0}    

END {PROCINFO["sorted_in"]="@ind_num_asc"
    n=292
    for ( id in vol ) { gsub(/^\t.../,"\t"n++,vol[id]) ; print vol[id] } }

허비하다

awk -f script inputfile

답변4

<infile awk -F';' -v RS= '
        /Collection one/{ n=$2; gsub(/[^0-9]*/, "", n); sub(/[0-9]+/, 292+n-1) }
        { print sep $0; sep="\0" }' |sort -z |tr '\0' '\n'

관련 정보