2012-05-19 6 views
6

Tengo un archivo, list.txt que contiene una lista de palabras. Quiero comprobar cuántas veces aparece cada palabra en otro archivo, file1.txt, y luego mostrar los resultados. Una salida sencilla de todos los números suficientes, ya que puedo añadir manualmente a list.txt con un programa de hoja de cálculo, pero si la secuencia de comandos agrega los números al final de cada línea en list.txt, que es aún mejor, por ejemplo:¿Cuántas veces aparece cada palabra de una lista de palabras en un archivo?

bear 3 
fish 15 

he intentado esto, pero no funciona:

cat list.txt | grep -c file1.txt 
+1

Olvidó mencionar el formato del archivo de entrada. Una palabra por linea? ¿Pueden las "palabras" tener espacios en blanco? ¿Qué pasa con el conjunto de datos en grep? – 0xC0000022L

+0

'list.txt1' es una palabra por línea. Una palabra puede tener algunos espacios. Los datos en 'archivo1.txt' son muchas oraciones, pero una línea nunca se rompe en múltiples líneas. – Village

Respuesta

8

Usted puede hacer esto en un bucle que lee una sola palabra a la vez de un archivo de lista de palabras, y luego cuenta los casos en una archivo de datos. Por ejemplo:

while read; do 
    echo -n "$REPLY " 
    fgrep -ow "$REPLY" data.txt | wc -l 
done < <(sort -u word_list.txt) 

La "salsa secreta" se compone de:

  1. utilizando la variable REPLY implícito;
  2. utilizando la sustitución de procesos para recopilar palabras del archivo de lista de palabras; y
  3. asegurándose de que está buscando expresiones completas en el archivo de datos.
+3

Esto contará el número de líneas coincidentes, no el recuento de ocurrencia real (si hay múltiples coincidencias en una línea, solo contará como una). En teoría, 'fgrep -o -c' debería arreglar esto, pero no funcionó correctamente en algunas versiones recientes de' coreutils' de GNU. – tripleee

+1

Gran captura, @tripleee. Ese fue un caso extremo que no había considerado. He actualizado la respuesta para abordar su caso de uso. –

3

Esto podría funcionar para usted (GNU SED):

tr -s ' ' '\n' file1.txt | 
sort | 
uniq -c | 
sed -e '1i\s|.*|& 0|' -e 's/\s*\(\S*\)\s\(\S*\)\s*/s|\\<\2\\>.*|\2 \1|/' | 
sed -f - list.txt 

Explicación:

  • de Split file1.txt en palabras
  • Ordenar las palabras
  • contar las palabras
  • Cree un script sed para mat ch las palabras (inicialmente cero cada palabra)
  • Run el script anterior en contra de la list.txt
4

Este método awk solamente tiene que pasar a través de cada archivo una vez:

awk ' 
    # read the words in list.txt 
    NR == FNR {count[$1]=0; next} 
    # process file1.txt 
    { 
    for (i=0; i<=NF; i++) 
     if ($i in count) 
     count[$i]++ 
    } 
    # output the results 
    END { 
    for (word in count) 
     print word, count[word] 
    } 
' list.txt file1.txt 
+0

+1 para ninguna clasificación, una sola pasada a través de la entrada, ningún archivo temporal. Si desea conservar el orden de 'list.txt' en la salida, es fácil agregar un índice en una segunda matriz al caso' NR == FNR'. – tripleee

1

comando sola línea

cat file1.txt |tr " " "\n"|sort|uniq -c |sort -n -r -k 1 |grep -w -f list.txt 

La última parte del comando le dice a grep que lea las palabras para que coincidan de la lista (opción -f) y luego las palabras completas (-w) es decir, si list.txt c ontains contiene auto, grep debe ignorar el carro.

Sin embargo, tenga en cuenta que la vista de la palabra completa y grep puede diferir. por ej. aunque el automóvil no coincidirá con el transporte, coincidirá con el lavado de automóviles, tenga en cuenta que "-" se considerará para el límite de palabras. grep toma cualquier cosa excepto letras, números y guiones bajos como límite de palabra. Lo cual no debería ser un problema ya que esto se ajusta a la definición aceptada de una palabra en inglés.

Cuestiones relacionadas