일

여기서 매개변수는 파일 이름입니다! 파일에 텍스트가 포함되어 있습니다. 스크립트의 임무는 어떤 단어가 다른 단어에 가장 자주 포함되는지 결정하는 것입니다.


입력 및 출력 예

(예: 텍스트는 다음과 같습니다. 공을 치다 축구 농구 눈덩이 - 공이 다른 세 세계의 일부이기 때문에 공이 승자입니다.)


내 코드 소파

지금까지 이 코드를 작성했지만 모든 출력에 대해 작동하지는 않습니다.

!/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 football3으로 계산됩니다 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}".

관련 정보