Como contar as ocorrências de cada palavra pertencente a um arquivo em todo o 'n' número de arquivos passados como argumentos?

1

Estou procurando um script de shell que aceite uma lista de nomes de arquivos como seus argumentos, conte e relate a ocorrência de cada palavra que está presente no primeiro arquivo de argumento em outros arquivos de argumento.

Tenho quase certeza de como contar as ocorrências de uma palavra em relação a um arquivo.

Isso é usando esse truque:

$ tr ' ' '\n' < FILE | grep -c WORD

Estou preso quando chega a n de arquivos.

Isso é o que eu vim até agora:

#!/bin/bash

if [ $# -lt 2 ]
    then
    echo "Very less arguments bro."
fi

 search_file='tr '\n' ' ' < $1' # Make the first file in to a sequence of words.

for other_file in "$@"
do
    if [ $other_file = $1 ]
        then 
        continue
    fi

    # Modify this file such that each space turns in to a newline
    tr ' ' '\n' < $other_file > new_temp_file

    for search_word in $search_file
    do
        word_freq='grep -c $search_word new_temp_file'
        echo "Word=$search_word Frequency=$word_freq"
    done
done
    
por The Room 07.09.2017 / 11:59

3 respostas

3

Eu faria:

#! /bin/sh -
# usage: wordcount <file-with-words-to-search-for> [<file>...]
words=$(tr -s '[[:space:]]' '[\n*]' < "${1?No word list provided}" | grep .)
[ -n "$words" ] || exit

shift
for file do
  printf 'File: %s\n' "$file"
  tr -s '[[:space:]]' '[\n*]' | grep -Fxe "$words" | sort | uniq -c | sort -rn
done

(isso só dá uma contagem para as palavras que são encontradas pelo menos uma vez em cada arquivo).

    
por 07.09.2017 / 12:26
1

Você pode fazer uma iteração em uma lista de arquivos fornecidos na linha de comando da seguinte forma:

for file in "$@"
do
    echo "Considering file ==> $file <=="
done

Seu método para correspondência de palavras deve ser perfeitamente eficaz. Você também pode procurar por ocorrências de uma palavra usando grep -o

echo 'I can cry cryogenic tears when I scry my hands. Can you cry too?' |
    grep -o '\bcry\b'    # \b marks a word boundary

Pipar o resultado disso em wc -l fornecerá o número de ocorrências no fluxo de entrada.

Usar $( ... ) permite interpolar a saída de um comando no texto usado por outro. Por exemplo

echo "The date and time right now is $(date)"

Precisamos de algum trabalho extra para evitar pesquisar o primeiro arquivo, mas usando isso como a lista de palavras. Mas juntando isso, você pode acabar assim:

wordfile="$1"
wordlist=($(cat "$wordfile"))
shift

for file in "$@"
do
    for word in "${wordlist[@]}"
    do
        # echo "$file: $word:" $(grep -o "\b${word}\b" "$file" | wc -l)  # My way
        echo "$file: $word:" $(tr ' ' '\n' <"$file" | grep -c "$word")   # Your way
    done
done

Não é muito eficiente porque, para N palavras, ele pesquisará cada arquivo N vezes. Você pode achar que grep -f é de ajuda aqui.

    
por 07.09.2017 / 12:12
0
fgrep -cw 'word' file1 file2 ... fileN

Isso gerará o seguinte:

file1:4
file2:16

e assim por diante, um por linha. Se é apenas o total de todos os arquivos, faça algo assim:

echo "Total: $(( $(fgrep -cw 'word' file1 file2 ... fileN | awk -F: '{ print $NF" + " }') 0 ))"

que produziria:

Total: 20
    
por 09.09.2017 / 06:57