Minería de texto plano

Minería de texto plano

(título original: grep en términos de párrafos, no de líneas)

Esta pregunta está motivada por fzf, lo que me permite localizar un determinado archivo en mi enorme sistema de archivos.de manera borrosa e incremental, brindando una experiencia de búsqueda muy, muy rápida (ve toneladas de lindos gifs en esteartículo).

Lo que tengo en mente es hacer cosas similares con mis notas. Tengo un montón de notas fugaces, diarios, memorandos, etc., en formato de texto sin formato. Paralegibilidad, cada línea no contiene más de 72 caracteres. Esto hace que sea difícil buscar en mi nota, según mi ingenuo conocimiento sobre las herramientas de búsqueda existentes como grep, ripgrep..

Ahora puedes mostrar (más/menos) contexto en torno a un patrón coincidente, pero eso no es lo que estoy pidiendo. Aquí incluyo un ejemplo para hacerlo más preciso.

1  Victim mentality is an acquired personality trait in which a person
2  tends to recognize or consider themselves as a victim of the negative
3  actions of others, and to behave as if this were the case in the face
4  of contrary evidence of such circumstances. Victim mentality depends
5  on clear thought processes and attribution.
6
7  (from wikipedia: Victim mentality)

Digamos que tomé esta nota hace medio año y sabía que estaba en algún lugar de mi sistema de archivos. Como siempre, no podemos recitar las palabras exactas, perorecordamos el contexto! grepLeer textos como personality, clear thoughto victimsobre mi sistema de archivos probablemente me darátambiénHay muchas cosas relevantes para mí que realmente puedo reducir.

Debería haber una herramienta (existente o no) que ayude a buscar textos como este.Nuestras notas antiguas (en texto plano) serán mucho más valiosas. ¿Hay alguna manera de hacerlo con nuestro buen viejo amigo grepy sus familiares? ¿O hay otras formas que funcionarían? Cualquier opinión también es muy apreciada.

Respuesta1

Dividamos el proceso (de búsqueda) en partes más pequeñas.

Primero necesitamos obtener una lista de archivos dentro de los cuales desea buscar, como en el directorio actual ( .) todos los archivos con extensión txt ( -name "*.txt") que ciertamente son archivos ( -type f):

find . -name "*.txt" -type f

Este resultado se puede usar como entrada para grepbuscar somethingdentro de esos archivos, incluido el número de línea y el nombre del archivo en la salida, ignorando mayúsculas y minúsculas ( -nHi), +al final se asegura de que todos los archivos se graben en una ejecución (no uno a la vez):

find . -name "*.txt" -type f -exec grep -nHi 'something' {} +

Si el número de archivos es demasiado grande (> $ARG_MAX), debe reemplazar+con \;.

La salida del comando anterior es algo como:

./some/dir/somewhere/songs.txt:128:But had me believing it was always something that I'd done
./some/dir/somewhere/songs.txt:883:Was never something I pursued
./some/dir/somewhere/songs.txt:2905:I know something about love 
./some/dir/somewhere/songs_other.txt:11780:will come across something like this:  F (Dshape).

Entonces, si divides esas líneas, :obtendrás 3 componentes: nombre de archivo, número de línea donde se encontró la coincidencia y la línea misma.

Ahora, si mantiene esta información para cada archivo coincidente, puede buscar los siguientes términos y sumar la distancia coincidente para encontrar archivos donde los términos buscados sean los más cercanos.

Para su texto de ejemplo, si busca sus 3 términos ( personality,, ) clear thought, victimobtendrá los números de línea correspondientes como 1, 5 y 2, por lo que la distancia para este archivo es (que se origina desde el primer término)

abs(1-5) + abs(1-2) = 5 

De esta forma, podrá ordenar los archivos según contengan todos los términos y los tenga más cerca de ese archivo.

Por supuesto, esto no es el panorama completo, por ejemplo, algunos archivos contienen el mismo término varias veces y este algoritmo tiene que tomar algunas decisiones sobre cómo calcular distancias, pero creo que lo anterior es algo para comenzar.

Respuesta2

Una simple frase en Perl puede hacer el trabajo. Lo siguiente imprimirá el nombre del archivo seguido de "encontrado" si todas las palabras clave (es decir, personalityy clear thoughty victimestán presentes en el archivo).

perl -0777 -ane 'print "$ARGV: found\n" if /^(?=.*personality)(?=.*clear thought)(?=.*victim)/s' file.txt 

Producción:

file.txt: found

Explicación:

-0777       # slurp mode
-ane        # read the file ans execute the following
print "$ARGV: found\n"      # print,$ARGV contains the current filename
if                          # if
  /                         # regex delimiter
    ^                       # begining of file
      (?=.*personality)     # positive lookahead, make sure we have "personality"
      (?=.*clear thought)   # positive lookahead, make sure we have "clear thought"
      (?=.*victim)          # positive lookahead, make sure we have "victim"
  /s                        # regex delimiter, s = dot matches newline

Si desea buscar en todos los archivos txt, utiliceperl ...... *.txt

información relacionada