저는 Bash 스크립팅을 배우고 있는데 이 문제로 어려움을 겪고 있습니다. 에서 여러 행이 주어지면 STDIN
먼저 길이에 따라 오름차순으로 정렬합니다. 그런 다음 동일한 문자 수가 포함된 행이 있으면 행에 포함된 공백이 아닌 문자 수에 따라 오름차순으로 정렬됩니다.
나는 몇 가지 다른 접근 방식을 시도했지만 일반적으로 Bash의 특이한 특성에 갇히게 됩니다.
이것이 내가 지금까지 얻은 것입니다:
#!/bin/bash
sorted=()
while IFS='' read -r line; do
length=${#line}
if [[ ${sorted[$length]} == "" ]] ; then
sorted[$length]="$line"
else
#non unique length
#sorted[$length]="${sorted[$length]}\n$line"
IFS=$'\n' arr=("${sorted[$length]}")
arr+=("$line")
spaces=()
for ((i=0 ; i < ${#arr[@]} ; ++i )) ; do
spaces[$i]=$(echo "${arr[$i]}" | sed "s: : \n:g" | grep -c " ")
done
arr_sorted=()
for ((i =0 ; i < ${#spaces[@]} ; i++ )) ; do
for ((j=0 ; j < ${#arr[@]} ; i++ )) ; do
this_line_length=$(echo "${arr[$j]}" | sed "s: : \n:g" | grep -c " ")
if [[ "$this_line_length" == "${spaces[$i]}" ]] ; then
arr_sorted+=("${arr[$j]}")
unset arr[$j]
fi
done
done
sorted[$length]="${arr_sorted[@]}"
fi
done
나는 이것이 최선의 접근 방식과는 거리가 멀다고 추측할 것입니다. bash 내장 기능에 너무 의존하지 않고 모든 것을 구현하려고 노력했지만 지금은 의미가 없어 보입니다.
답변1
다른 원칙과 동일한 원칙을 사용하되(공백 문자 유무에 관계없이 줄 길이를 구하고 정렬한 다음 제거) 다음을 사용합니다 awk
.
awk '{NC = length(gensub(/[[:space:]]/, "", "g")); print length, NC, $0}' file |
sort -nk1,2 |
sed -r 's/^([0-9]+ ){2}//'
gensub(/[[:space:]]/, "", "g")
줄에서 모든 공백 문자를 제거하면 나머지 문자열의 길이를 얻습니다.
코드 블록까지 질문 텍스트를 사용하고 너비는 80자로 축소됩니다.
$ awk '{NC = length(gensub(/[[:space:]]/, "", "g")); print length, NC, $0}' foo | sort -nk1,2 | sed -r 's/^([0-9]+ ){2}//'
increasing order).
Here's what I've got so far:
f the idiosyncrasies of bash.
iven a bunch of lines from STDIN, sort them first by the length of the line in i
I've tried this a couple of different ways but I usually get caught up in some o
, sort them by the number of nonblank characters contained in the lines (also in
I am working on learning bash scripting but I am struggling with this problem. G
ncreasing order. Then, if there are any lines with the same number of characters
답변2
sort
다음 과 같은 악의적인 외부 장치를 사용하도록 허용된 경우 cut
:
#! /bin/bash
while IFS= read -r line; do
squeezed=$( tr -d '[:blank:]' <<<"$line" )
printf '%d\t%d\t%s\n' ${#line} ${#squeezed} "$line"
done | sort -n -k 1 -k 2 | cut -f 3-
편집하다:모두가 그렇게 하기 때문에 해결책은 다음과 같습니다 perl
.
perl -e 'print sort { length $a <=> length $b || $a =~ y/ \t//c <=> $b =~ y/ \t//c } <>'
답변3
순수한세게 때리다
입력이 작을수록 포크가 없기 때문에 다른 답변보다 훨씬 빠릅니다!
sortByLength () {
local -a sorted=() sort2
local line sline sline2 pointer
while IFS= read -r line; do
sorted[${#line}]+="$line."
done
for pointer in ${!sorted[@]} ;do
sort2=()
line="${sorted[pointer]}"
while [ "$line" ]; do
sline=${line:0:pointer}
line=${line:pointer+1}
sline2=${sline//[[:blank:]]}
sort2[${#sline2}]+=${sline}$'\n'
done
printf "%s" "${sort2[@]}"
done
}
왜냐하면 이것은 다음과 같기 때문이다숙제, 이것이 어떻게 작동하는지 설명하겠습니다 ...
포크는 1개면 충분해요진주
sortByLength () {
perl -e '
while(<>){
chomp;
push @a,$_;
};
map {
printf "%s\n",${$_}[2];
} sort {
${$a}[0]*1000+${$a}[1] <=> ${$b}[0]*1000+${$b}[1]
} map {
my $s=$_;
s/\s//g;
[ length($s),length($_),$s ]
} @a;
'
}
답변4
기능:
sortlen() { while read x ; do \
y=`tr -d '[:blank:]' <<< "$x"` ; echo ${#x} ${#y} "$x" ; \
done | sort -k 1g,2 -k 2g,3 | cut -d' ' -f3-; }
시험:
printf "a b c\nabcde\nabcdefg\na\nabcd\n" | sortlen
산출:
a
abcd
a b c
abcde
abcdefg