공백을 포함한 줄 길이별로 텍스트 파일 정렬
다음과 같은 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)입니다.
결과.
- Caleb의 솔루션은 11.2초가 걸렸습니다.
- 솔루션을 구축하는 데 11.6초가 걸렸습니다.
- 닐브의 솔루션 #1은 20초가 걸렸습니다.
- 닐브의 솔루션 #2는 23초가 걸렸습니다.
- 아부바의 용액은 24초가 걸렸습니다.
- 조나단의 솔루션은 25초가 걸렸습니다.
- 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
그자리의 -g
general-general-gen-gen) ) -n
1988-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.
다음은 선을 길이별로 정렬하는 멀티바이트 호환 방법입니다.요구 사항:
wc -m
사용할 수 있습니다(macOS가 보유).- 현재 로케일은 설정을 통해 다중 바이트 문자를 지원합니다.
LC_ALL=UTF-8
.bash_profile에서 설정하거나 다음 명령 앞에 추가하여 설정할 수 있습니다. 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
'programing' 카테고리의 다른 글
Postgre에서 테이블의 행 수를 빠르게 검색하는 방법SQL (0) | 2023.05.25 |
---|---|
app.config에 의존하지 않고 SOAP 웹 서비스를 사용합니다. (0) | 2023.05.25 |
각 루프에 대해 루프의 마지막 반복을 결정합니다. (0) | 2023.05.25 |
할당 표현식이란 무엇입니까("왈러스" 또는 ":=" 연산자 사용)?이 구문이 추가된 이유는 무엇입니까? (0) | 2023.05.25 |
Winforms에서 컨트롤에 대한 속성 바인딩 (0) | 2023.05.25 |