programing

공백을 포함한 줄 길이별로 텍스트 파일 정렬

testmans 2023. 5. 25. 21:38
반응형

공백을 포함한 줄 길이별로 텍스트 파일 정렬

다음과 같은 CSV 파일이 있습니다.

AS2345, ASDF1232, Mr. Plain 예제, 110 이진법,아틀란티스,RI,12345,(999)123-5555,1.56AS2345, ASDF1232, Mrs. Plain Example, 1121110 Ternary st. 110 이진 평균., 아틀란티스,RI,12345,(999)123-5555,1.56AS2345, ASDF1232, Mr. Plain 예제, 110 이진법,리버티 시티, RI, 12345, (999) 123-5555, 1.56AS2345, ASDF1232, Mr. Plain Example, 110 Thernary ave.,Some City, RI, 12345, (999) 123-5555, 1.56

저는 공백을 포함한 줄 길이별로 분류해야 합니다.다음 명령어는 공백이 포함되어 있지 않은데, 제가 사용할 수 있도록 수정할 수 있는 방법이 있나요?

cat $@ | awk '{ print length, $0 }' | sort -n | awk '{$1=""; print $0}'

정답.

cat testfile | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2-

또는 같은 길이의 선을 원래(의도하지 않은 것일 수 있음) 하위 정렬을 수행하려면 다음을(를 수행합니다.

cat testfile | awk '{ print length, $0 }' | sort -n | cut -d" " -f2-

두 경우 모두 당신의 최종 컷을 위해 어색함에서 벗어나 당신의 언급된 문제를 해결했습니다.

일치하는 길이의 선 - 동점일 경우 수행할 작업:

질문에서 일치하는 길이의 선에 대해 추가 정렬을 원하는지 여부를 지정하지 않았습니다.저는 않는 것이라고 했습니다.-s(--stable하여 해당 를 사용하여 이러한 행이 서로 정렬되지 않도록 하고 입력에서 발생하는 상대적인 순서대로 유지합니다.

(을 더 잘sort'를 볼 수 --key옵션).

질문의 시도된 해결책이 실패하는 이유(워크 라인 재구축):

다음과 같은 차이점에 주목하는 것은 흥미로운 일입니다.

echo "hello   awk   world" | awk '{print}'
echo "hello   awk   world" | awk '{$1="hello"; print}'

그들은 각각 양보합니다.

hello   awk   world
hello awk world

(gawk's) 매뉴얼의 관련 섹션에서는 하나의 필드를 변경할 때 awk가 0달러 전체를 재구축한다는 측면만 언급하고 있습니다.미친 행동이 아닌 것 같아요.다음이 포함됩니다.

"마지막으로, 필드와 OFS의 현재 값을 사용하여 전체 레코드를 강제로 재구축하는 것이 편리할 때가 있습니다.이렇게 하려면 겉보기에는 무해한 할당을 사용하십시오."

 $1 = $1   # force record to be reconstituted
 print $0  # or whatever else with $0

"이것은 기록을 다시 세우는데 어색함을 강요합니다."

길이가 같은 일부 라인을 포함한 테스트 입력:

aa A line   with     MORE    spaces
bb The very longest line in the file
ccb
9   dd equal len.  Orig pos = 1
500 dd equal len.  Orig pos = 2
ccz
cca
ee A line with  some       spaces
1   dd equal len.  Orig pos = 3
ff
5   dd equal len.  Orig pos = 4
g

정말로 사용하고 싶다면 닐브의 AWK 솔루션이 좋습니다.awk, 이라면, 한 가지 해결책은 , 든않상하지하관한것좋사솔가용은을션해면루지책결다는이속거로▁perl의▁is▁and,▁solution▁explains▁to▁one▁it▁it것'▁why▁what▁use다사니입▁but는하용▁if솔을'▁done▁want▁what▁perl▁is션은s▁yous책,▁there▁yousort()사용자 정의 Caparison 루틴을 사용하여 입력 라인을 통해 반복할 수 있습니다.다음은 하나의 라이너입니다.

perl -e 'print sort { length($a) <=> length($b) } <>'

로 하는 수. STDIN (from 필한곳으어이면로파넣에인수있라다니신. STDIN (십시하요오수습든을).cat또는 셸 리디렉션) 또는 다른 인수로 펄에 파일 이름을 지정하고 파일을 열 수 있도록 합니다.

제 경우에는 가장 긴 줄이 먼저 필요해서 교체했습니다.$a그리고.$b비교하면

벤치마크 결과

다음은 이 질문에 대한 다른 답변의 솔루션 전반에 걸친 벤치마크 결과입니다.

시험방법

  • 고속 시스템에서 10회 연속 실행, 평균
  • Perl 5.24
  • awk 3.1.5 (gawk 4.1.0배가 ~2% 더 빠름)
  • 입력 파일은 550MB, 600만 줄 괴물(영국 국립 코퍼스 txt)입니다.

결과.

  1. Caleb의 솔루션은 11.2초가 걸렸습니다.
  2. 솔루션을 구축하는 데 11.6초가 걸렸습니다.
  3. 닐브의 솔루션 #1은 20초가 걸렸습니다.
  4. 닐브의 솔루션 #2는 23초가 걸렸습니다.
  5. 아부바의 용액은 24초가 걸렸습니다.
  6. 조나단의 솔루션은 25초가 걸렸습니다.
  7. Fritz의 솔루션은 다음 솔루션보다 400배 더 오래 걸립니다.awk솔루션(100000줄의 잘린 테스트 사례 사용).잘 작동합니다. 시간이 오래 걸립니다.

하나의 른다.perl

perl -ne 'push @a, $_; END{ print sort { length $a <=> length $b } @a }' file

대신 다음 명령을 사용하십시오.

awk '{print length, $0}' your-file | sort -n | cut -d " " -f2-

순수한 배쉬:

declare -a sorted

while read line; do
  if [ -z "${sorted[${#line}]}" ] ; then          # does line length already exist?
    sorted[${#line}]="$line"                      # element for new length
  else
    sorted[${#line}]="${sorted[${#line}]}\n$line" # append to lines with equal length
  fi
done < data.csv

for key in ${!sorted[*]}; do                      # iterate over existing indices
  echo -e "${sorted[$key]}"                       # echo lines with equal length
done

파이썬 솔루션

다음은 Python 3.9.10 및 2.7.18에서 테스트된 동일한 기능을 수행하는 Python 원라이너입니다.Caleb의 Perl 솔루션보다 약 60% 빠르며 출력은 동일합니다(1480만 줄의 300MiB 워드리스트 파일로 테스트).

python -c 'import sys; sys.stdout.writelines(sorted(sys.stdin.readlines(), key=len))'

벤치마크:

python -c 'import sys; sys.stdout.writelines(sorted(sys.stdin.readlines(), key=len))'
real    0m5.308s
user    0m3.733s
sys     0m1.490s

perl -e 'print sort { length($a) <=> length($b) } <>'
real    0m8.840s
user    0m7.117s
sys     0m2.279s

length()함수에는 공백이 포함됩니다.저는 (UUOC를 피하는 을 포함하여) 당신의 파이프라인을 약간 조정할 것입니다.

awk '{ printf "%d:%s\n", length($0), $0;}' "$@" | sort -n | sed 's/^[0-9]*://'

sed은 명은직접추가숫콜자제론거다니합을와된에 합니다.awk지또권 또는는서유지에서 서식을 합니다.awk:

awk '{ print length($0), $0;}' "$@" | sort -n | sed 's/^[0-9]* //'

파일에 숫자로 시작하는 줄이 포함되어 있으면 이러한 해결책이 작동하지 않습니다. 계산된 모든 줄과 함께 숫자로 정렬되기 때문입니다.해결책은 주는 것입니다.sort그자리의 -ggeneral-general-gen-gen) ) -n1988-1988):

awk '{ print length, $0 }' lines.txt | sort -g | cut -d" " -f2-

POSIX Awk 포함:

{
  c = length
  m[c] = m[c] ? m[c] RS $0 : $0
} END {
  for (c in m) print m[c]
}

순전한 어색한 해결책줄 길이가 1024보다 클 수 없다고 가정합니다.

cat filename | awk 'BEGIN {min = 1024; s = ";} {l = "";} {l = l; s = $0;} END {prints}'

하나의 라이너 바시 솔루션은 모든 라인에 단어가 하나만 있다고 가정하지만, 모든 라인에 단어 수가 동일한 경우에 대해 재작업할 수 있습니다.

LINE=$(cat 파일 이름); $LINES에 k; printf "$k"; echo $k | wc -L; 완료 | sort -k2 | head -n1 | cut -d " " -f1

Raku(이전 이름: Perl6) 사용

~$ cat "BinaryAve.txt" | raku -e 'given lines() {.sort(*.chars).join("\n").say};'

AS2345,ASDF1232, Mr. Plain Example, 110 Binary ave.,Atlantis,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mr. Plain Example, 110 Ternary ave.,Some City,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mr. Plain Example, 110 Binary ave.,Liberty City,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mrs. Plain Example, 1121110 Ternary st.                                        110 Binary ave..,Atlantis,RI,12345,(999)123-5555,1.56

정렬을 되돌리려면 추가.reverse일련의 메서드 호출 중에 바로 다음에.sort()다음 코드는 다음과 같습니다..chars공백 포함:

~$ cat "number_triangle.txt" | raku -e 'given lines() {.map(*.chars).say};'
(1 3 5 7 9 11 13 15 17 19 0)
~$ cat "number_triangle.txt"
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 0

다음은 9.1을 사용한 awk와 Raku의 시간 비교입니다.Genbank의 MBtxt 파일:

~$ time cat "rat_whole_genome.txt" | raku -e 'given lines() {.sort(*.chars).join("\n").say};' > /dev/null
    
    real    0m1.308s
    user    0m1.213s
    sys 0m0.173s
    
~$ #awk code from neillb
~$ time cat "rat_whole_genome.txt" | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2-  > /dev/null
    
    real    0m1.189s
    user    0m1.170s
    sys 0m0.050s

HTH.

https://raku.org

다음은 선을 길이별로 정렬하는 멀티바이트 호환 방법입니다.요구 사항:

  1. wc -m사용할 수 있습니다(macOS가 보유).
  2. 현재 로케일은 설정을 통해 다중 바이트 문자를 지원합니다.LC_ALL=UTF-8.bash_profile에서 설정하거나 다음 명령 앞에 추가하여 설정할 수 있습니다.
  3. testfile사용자 로케일(예: UTF-8)과 일치하는 문자 인코딩이 있습니다.

다음은 전체 명령입니다.

cat testfile | awk '{l=$0; gsub(/\047/, "\047\"\047\"\047", l); cmd=sprintf("echo \047%s\047 | wc -m", l); cmd | getline c; close(cmd); sub(/ */, "", c); { print c, $0 }}' | sort -ns | cut -d" " -f2-

부품별 설명:

  • l=$0; gsub(/\047/, "\047\"\047\"\047", l); 각 행의 복사본을 awk 변수로 만듭니다.l 매 리 매 두 번 반 복 합 니 다 escapes 그 번 고 ▁every - ▁and ▁double escapes 다 니 합 반' 수 (라인이셸명안반수있록도향될게하전로령으▁so▁(록라,\047는 8진수 표기의 단일 문자입니다.
  • cmd=sprintf("echo \047%s\047 | wc -m", l); 이것이 우리가 실행할 명령이며, 탈출선을 반향시킵니다.wc -m.
  • cmd | getline c; 명령을 실행하고 Awk 변수로 반환되는 문자 카운트 값을 복사합니다.c.
  • close(cmd); 셸 명령에 대한 파이프를 닫아 한 프로세스에서 열려 있는 파일 수에 대한 시스템 제한에 도달하지 않도록 합니다.
  • sub(/ */, "", c); 반환된 문자 수 값에서 공백을 자릅니다.wc.
  • { print c, $0 } 줄의 문자 수 값, 공백 및 원래 줄을 인쇄합니다.
  • | sort -ns 숫자로 줄을 정렬합니다(접두사 문자 수 값 기준).-n순서 (), 안적인정순렬유지서정()-s).
  • | cut -d" " -f2- 추가된 문자 수 값을 제거합니다.

각 라인에 대해 하위 명령을 실행해야 하기 때문에 속도가 느립니다(빠른 맥북 프로의 경우 초당 160줄에 불과함)

또는 이 작업만 수행할 수 있습니다.gawk(버전 3.1.5에서 Gawk는 멀티바이트 인식), 이는 훨씬 더 빠를 것입니다. 및 것은 할 수 ). awk 서 셸 위 라 이 모 전 및 있 어 많 것 은사 는 은 려 하 이것이 추가 소프트웨어를 설치할 필요가 없는 유일한 방법입니다(macOS에서는 기본적으로 gawk를 사용할 수 없습니다)

다시 방문하는 것.이렇게 접근했습니다(LINE 길이를 세어 LEN으로 저장, LEN별로 정렬, LINE만 유지).

cat test.csv | while read LINE; do LEN=$(echo ${LINE} | wc -c); echo ${LINE} ${LEN}; done | sort -k 2n | cut -d ' ' -f 1     

언급URL : https://stackoverflow.com/questions/5917576/sort-a-text-file-by-line-length-including-spaces

반응형