일
여기서 매개변수는 파일 이름입니다! 파일에 텍스트가 포함되어 있습니다. 스크립트의 임무는 어떤 단어가 가장 자주 포함되는지(즉) 결정하는 것입니다.
입력 및 출력 예
(예를 들어 텍스트는 공 공, 축구, 농구, 눈덩이입니다. 따라서 공은 다른 세 세계의 일부이므로 승자가 됩니다.)
지금까지 내 코드
지금까지 이 코드를 작성했지만 모든 출력에 대해 작동하지는 않습니다.
!/bin/sh
awk '{for(i=2;i<NF;i++) {s=$i; for(j=i+1;j<=NF;j++) print s=s FS $j}}' $1 | sort | uniq -c | sort -k1,1rn -k2 | sed 's/ *[^ ]* *//;q' | cut -f1 -d" "
답변1
words
단어 목록이 한 줄에 한 단어만 있는 파일에 있는 경우 ( tr ' ' '\n' <originalwords >words
원래 목록을 여러 줄로 분할하는 데 사용하여 생성되었을 수 있음) 루프를 실행합니다.
while IFS= read -r word; do
grep -F -o -e "$word" words
done <words | awk '{ c[$0]++; if (c[$0] > c[w]) w = $0 } END { print w }'
단어 목록의 일부로 가장 자주 나타나는 단어를 출력합니다(또는 많은 단어가 동일한 횟수로 나타나는 경우 목록에서 해당 단어가 처음 나타나는 단어).
이는 목록 자체를 목록과 일치시킬 패턴 집합으로 사용하여 수행됩니다. -o
일치하는 하위 문자열이 별도의 줄에 반환되어야 합니다 .
루프 단독의 출력과 질문에 제공된 목록은 다음과 같습니다.
play
ball
ball
ball
ball
football
basketball
snowball
그런 다음 단어 수를 세어 가장 자주 나타나는 단어를 선택하세요.
임시 파일 처리가 포함된 완전한 스크립트:
#!/bin/sh
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT # delete temporary file upon exiting
tr -s ' ' '\n' <"${1:-/dev/stdin}" >"$tmpfile" # convert into word list
while IFS= read -r word; do
grep -F -o -e "$word" "$tmpfile"
done <"$tmpfile" | awk '{ c[$0]++; if (c[$0] > c[w]) w = $0 } END { print w }'
파일을 지정하지 않으면 스크립트는 표준 입력에서도 읽습니다.
답변2
awk '{
for (i=1; i<=NF; i++) {
uwords[$i] = 0
allwords[++idx] = $i
}
}
END {
if (idx == 0) exit
max = 0
for (w in uwords) {
count = 0
for (i=1; i<=idx; i++) {
if (allwords[i] ~ w) count++;
}
if (count > max) {
max = count
maxw = w
}
}
print maxw
}'
입력을 스캔하고 고유 단어 목록과 모든 단어 목록을 추출합니다. (고유한 단어 목록은 필요하지 않을 것 같지만 입력이 클수록 작업이 더 효율적일 수 있습니다.) 그런 다음 각 고유 단어에 대해 파일에서 일치하는 단어 수를 세어보세요. (따라서 파일에 가 포함되어 있으면 football football football
3번으로 이동하세요. ball
) 가장 일치하는 항목을 추적하세요.
uwords
동점인 경우 (고유 단어) 배열의 첫 번째 발생을 보고합니다. 이것이 반드시 파일에 나타나는 첫 번째 항목은 아니며 알파벳순으로 첫 번째 항목도 아닙니다.
단어에 다음이 포함되면 예상치 못한 결과가 발생할 수 있습니다..
, *
또는 [
.
Kusalananda의 shell+awk 접근 방식을 선호하지만 극단적인 경우 오류를 원하지 않는 경우 다음을 수행하십시오.
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT # delete temporary file upon exiting
tr -s ' ' '\n' < "${1:-/dev/stdin}" > "$tmpfile" # convert into word list
sort -u "$tmpfile" | while IFS= read -r word
do
grep -F -o -e "$word" "$tmpfile"
done | awk '{ c[$0]++; if (c[$0] > c[w]) w = $0 } END { print w }'
단어 목록을 정렬하면 고유한 단어 목록이 얻어지므로 어떤 단어도 두 번 이상 계산되지 않습니다.
이 코드는 최대 하나의 입력 파일이 있다고 명시적으로 가정합니다(그러나 파일이 없을 수도 있습니다. 즉, stdin에서 읽는 것). 이는 질문의 표현과 일치합니다. 그러나 입력 파일이 여러 개 있을 경우(0, 1,이상), tr
행을 다음으로 변경하십시오.
cat -- "$@" | tr -s ' ' '\n' > "$tmpfile" # convert into word list
UUOC라고 할 수 있지만
- 두 개 이상의 입력 파일이 있는 경우를 처리합니다.
- 에 비해 읽기가 더 쉽습니다
< "${1:-/dev/stdin}"
.