다음과 같은 긴 숫자 목록이 있습니다.
1234-212-22-11153782-0114232192380
8807698823332-6756-234-14-09867378
45323-14-221-238372635363-43676256
62736373-9983-23-234-8863345637388
. . . .
. . . .
나는 두 가지 일을 하고 싶다:
1) 각 세그먼트 내의 비트 수에 따라 목록을 정렬하면 출력은 다음과 같아야 합니다.
22-212-1234-11153782-0114232192380
14-234-6756-09867378-8807698823332
14-221-45323-43676256-238372635363
23-234-9983-62736373-8863345637388
2) 각 줄의 하위 문자열 수를 찾으면 출력은 다음과 같아야 합니다.
2-3-4-8-13
2-3-4-8-13
2-3-5-8-12
2-3-4-8-13
이 예에서 각 번호의 첫 번째, 두 번째, 세 번째 세그먼트는 동일한 번호를 갖지만 다를 수 있습니다.
답변1
어때요?
$ perl -F'-' -lpe '$_ = join "-", sort { length $a <=> length $b } @F' file
22-212-1234-11153782-0114232192380
14-234-6756-09867378-8807698823332
14-221-45323-43676256-238372635363
23-234-9983-62736373-8863345637388
그리고
$ perl -F'-' -lpe '$_ = join "-", sort { $a <=> $b } map length, @F' file
2-3-4-8-13
2-3-4-8-13
2-3-5-8-12
2-3-4-8-13
감사해요스티븐 차제라스제안된 개선사항
답변2
GNU awk는 정렬할 수 있으므로 가장 까다로운 부분은 원하는 두 개의 출력을 분리하는 방법을 결정하는 것입니다. 스크립트는 두 개의 결과를 생성하며 이를 하드 코딩된 출력 파일이 아닌 다른 위치에 원하는지 결정할 수 있습니다.
function compare_length(i1, v1, i2, v2) {
return (length(v1) - length(v2));
}
BEGIN {
PROCINFO["sorted_in"]="compare_length"
FS="-"
}
{
split($0, elements);
asort(elements, sorted_elements, "compare_length");
reordered="";
lengths="";
for (element in sorted_elements) {
reordered=(reordered == "" ? "" : reordered FS) sorted_elements[element];
lengths=(lengths == "" ? "" : lengths FS) length(sorted_elements[element]);
}
print reordered > "reordered.out";
print lengths > "lengths.out";
}
답변3
이것이 당신에게 얼마나 도움이 될까요?
awk -F- ' # set "-" as the field separator
{
for (i=1; i<=NF; i++){
L = length($i) # for every single field, calc its length
T[L] = $i # and populate the T array with length as index
if (L>MX){ MX = L } # keep max length
}
$0 = "" # empty line
for (i=1; i<=MX; i++){
if (T[i]){
$0 = $0 OFS T[i] # append each non-zero T element to the line, separated by "-"
C = C OFS i # keep the field lengths in separate variable C
}
}
print substr ($0, 2) "\t" substr (C, 2) # print the line and the field lengths, eliminating each first char
C = MX = "" # reset working variables
split ("", T) # delete T array
}
' OFS=- file
22-212-1234-11153782-0114232192380 2-3-4-8-13
14-234-6756-09867378-8807698823332 2-3-4-8-13
14-221-45323-43676256-238372635363 2-3-5-8-12
23-234-9983-62736373-8863345637388 2-3-4-8-13
인쇄물을 두 개의 결과 파일로 분할할 수 있습니다.
답변4
Bash 파이프를 사용하여 작성할 수 있습니다.
while IFS=- read -ra words; do
for word in "${words[@]}"; do printf "%d\t%s\n" "${#word}" "$word"; done |
sort -k1,1n |
cut -f2 |
paste -sd-
done < file