문자열로 시작하는 필드에 따라 파일 정렬

문자열로 시작하는 필드에 따라 파일 정렬

이렇게 구조화된 파일이 있다고 가정해 보겠습니다.

/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/zz/Books/Author-Zigniwe-Hisory-Medicine.pdf
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf

파일을 다음과 같이 정렬하고 싶습니다.

/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/zz/Books/Author-Zigniwe-History-Medicine.pdf

즉, 문자열에 따라 알파벳순으로Author-...

보시다시피 의 위치는 Author-...일정하지 않습니다.

어떻게 해야 하나요?

답변1

다음 bash명령을 시도해 보십시오:

sort -t- -d -k2 -o output.txt input.txt

여기에는 입력 파일 이름과 함께 네 가지 옵션이 있습니다 input.txt. 이 파일이 현재 디렉터리에 없으면 path/to/the/folder/input.txt. 옵션과 해당 인수는 다음과 같습니다.

  • -t는 필드 구분 기호를 표시합니다. -구분 기호로 사용하여 앞과 뒤의 모든 항목이 -별도의 열로 간주됩니다.
  • -d는 사전 정렬을 나타냅니다. 예를 들어 Apple은 Berry 이전입니다.
  • -k2는 정렬 기준이 되는 열(이 경우 두 번째 열)을 나타냅니다. 첫 번째 열은 첫 번째 열 이전의 모든 항목입니다 -. 예를 들어, /home/zz/BOOKS/Author. 두 번째 열은 첫 번째와 두 번째 열 사이 -, 즉 입니다 Artemis.
  • -o는 output.txt정렬된 출력을 터미널이 아닌 파일로 리디렉션합니다.

도움이 되었기를 바랍니다

답변2

현재 예제에서는 너무 과도하지만user68186의 답변에서 제안된 솔루션, GNU awk에서 더 일반적으로 다음과 같은 작업을 수행할 수 있습니다.

gawk -F/ '
  function mycmp(i1,v1,i2,v2) {
    m = split(v1,a);
    n = split(v2,b);
    return a[m]"" > b[n]"" ? 1 : a[m]"" < b[n]"" ? -1 : 0
  }
  {
    lines[NR] = $0
  }
  END {
    PROCINFO["sorted_in"] = "mycmp";
    for(i in lines) print lines[i]
  }
' file

마지막 이후의 모든 항목의 어휘 값에 따라 정렬됩니다 /. 따라서 형식이 Author-<author name>-<title>.<extension>다음과 같을 경우

  • 고정 문자열 Author-(모든 행에 대해 동일한 가중치를 갖기 때문에 효과가 없음) 그 다음에
  • <author name>-; 그 다음에
  • <title>.; 그 다음에
  • <extension>

sort이는 GNU 의 간단한 KEYDEF 작동 방식과 유사합니다. -t- -k2즉, 효과적인 정렬 키는 에서 시작하여 <author name>줄 끝까지 계속됩니다.

split의 값을 상속하도록 호출 에서 명시적 구분 기호가 생략되므로 FS다른 경로 구분 기호를 사용하는 시스템에서 쉽게 변경할 수 있습니다. 파일 이름이 숫자인 경우에도 함수 ""에 추가된 빈 문자열은 어휘 비교를 강제합니다. 예를 참조하세요.mycmpawk가 문자열과 숫자 사이를 변환하는 방법


명령 을 계속 사용하고 싶다면 sortGNU awk를 활용할 수 있습니다.다른 프로세스와의 양방향 통신에게:

  • /문자열 시작 부분에 마지막으로 구분된 필드를 복제합니다.
  • 결과를 sort명령 에 전달
  • 정렬된 결과를 다시 읽고, 중복된 접두사를 제거하고 인쇄합니다.

gawk -F/ '
  BEGIN {OFS=FS; cmd = "sort -d"} 
  {print $NF $0 |& cmd} 
  END {
    close(cmd,"to"); 
    while(cmd |& getline){$1 = ""; print};
    close(cmd,"from")
  }
' file

/절대 경로(로 시작하는 줄 )가 초기 빈 필드를 암시한다는 점에서 약간의 속임수가 있습니다 . 상대 경로를 처리하려면 "누락된" 구분 기호를 삽입하기 print $NF $0위해 변경해야 하며 , 선행 요소를 제거하려면 더 간단한 대신 print $NF,$0정규식을 사용해야 합니다 .sub()$1 = ""

순수 솔루션보다 잠재적으로 더 빠르고 메모리 효율성이 높을 뿐만 아니라 gawk다른 sort옵션을 직접 추가할 수도 있습니다. cmd = "sort -d -t " FS " -k1,1r".

관련 정보