Cómo hacer un motor de búsqueda personalizado en AppleScript

2

Tengo una base de datos de carpetas y archivos (.txt) y estoy tratando de crear un programa en el que pueda ingresar palabras clave y hacer que busque esos archivos, y generará el texto de cualquier archivo que contenga las palabras clave. Tengo un código de trabajo que hace precisamente eso, pero no busca las palabras individualmente, las busca juntas como una sola cadena.

Por ejemplo, si escribo "Joe Bill Bob", me gustaría que generara archivos que contengan cada una de esas palabras en cualquier lugar del archivo, incluso si no están uno al lado del otro, o en ese orden.

Preferiría evitar hacer un ciclo de repetición para ingresar un término de búsqueda a la vez.

También prefiero evitar configurar cientos de variables en el código y hacer un ciclo de repetición que, si un carácter no es un espacio, lo agrega a la primera variable en blanco y si lo hace, pasa a la siguiente variable .

Si tienes otras ideas, sería genial. Gracias!

    
pregunta DonielF 06.08.2017 - 20:17

2 respuestas

1

Nota : los archivos de texto deben codificarse con la codificación " UTF8 ".

Aquí hay un guión inicial:

Ejemplo : las palabras clave:

"Bill
Bob
Joe"

fgrep y ordenar líneas de retorno, como esto:

/path/of/thisFile.txt:Bill
/path/of/thisFile.txt:Bob
/path/of/thisFile.txt:Joe
/path/of/thisFile2.txt:Bob
/path/of/thisFile2.txt:Joe
/path/of/thisFile3.txt:Bob
/path/subf1/of/some_File.txt:Bill
/path/subf3/of/some_xzzz_File.txt:Bill

El script usa un bucle para verificar la ruta de cada elemento en esta lista.

La secuencia de comandos obtiene la ruta del primer elemento, elimina ": Bill" al final de la línea - > por lo tanto, la ruta es " /path/of/thisFile.txt ".

El script comprueba el elemento (índice actual + número de palabras clave -1), es el tercer elemento, por lo que el tercer elemento contiene la misma ruta, luego el script agrega la ruta a una nueva lista

Los demás elementos no contienen todas las palabras clave.

set r to text returned of (display dialog "What keywords?" default answer "Joe Bill Bob") --- each keyword must be sepearated by a space
set tKeys to my makeKeysForGrep(r)
if tKeys is not "" then
    set masterFolder to choose folder with prompt "Select the source folder .."
    set filesList to my getFilescontainingKeywords(masterFolder, tKeys) -- get a list of files ( each file contains all the keywords)
    --do something with the filesList -- this list contains path of type 'posix path' 
end if

on makeKeysForGrep(t)
    (***   delete trailing and leading spaces, replace multiple spaces in a row by one space (clean the string to avoid issue with the unnecessary spaces in the grep command),
     and replace the space character by a linefeed character , so each line contains a keyword.  ***)
    set r to do shell script "perl -pe 's/ +$|^ +//g; s/ +/ /g; s/ /\n/g; '  <<< " & (quoted form of t) & "| sort -u" without altering line endings
    if r is not linefeed then return text 1 thru -2 of r -- remove the last line (it's a blank line)
    return "" -- r is a a blank line, so return ""
end makeKeysForGrep

on getFilescontainingKeywords(dir, tKeys)
    script o
        property tfiles : {}
    end script
    set numOfKeywords to count (paragraphs of tKeys) -- get the number of keywords
    set tFolder to quoted form of POSIX path of dir
    set o's tfiles to do shell script "fgrep -R -o -w  --include \"*.txt\" " & (quoted form of tKeys) & " " & tFolder & " | sort -u"
    -- fgrep return the full path + ":" + the keyword, sort -u  : sort the paths and deletes duplicate lines (because the same file can contains multiple occcurences of a keyword)

    if o's tfiles is not "" then
        if numOfKeywords = 1 then return o's tfiles -- no need to continue because one keyword only,  return all Files
        set l to {}
        set o's tfiles to paragraphs of o's tfiles
        set tc to count o's tfiles
        set firstKeyword to ":" & (paragraph 1 of tKeys)
        set numCh to (length of firstKeyword) + 1
        set i to 1
        repeat while (i < tc) -- check each path in the list, the same path must exists  numOfKeywords  in a row 
            set thisItem to (item i of o's tfiles)
            if thisItem ends with firstKeyword then
                set textFilepath to text 1 thru -numCh of thisItem
                set j to (i + numOfKeywords - 1)
                if j > tc then exit repeat
                if (item j of o's tfiles) starts with textFilepath then -- this file contains all the keywords
                    set end of l to textFilepath --- append this path to the list
                    set i to i + numOfKeywords -- to skip items wich contains the same path
                else
                    set i to i + 1 -- next file
                end if
            else
                set i to i + 1 -- next file
            end if
        end repeat
        return l -- list of files which contains all the keywords
    end if
    return {} -- No files found
end getFilescontainingKeywords

Las opciones de fgrep :

  • La opción --include \"*.txt\" : solo archivos que coincidan con los dados se busca el patrón de nombre de archivo, por lo que cualquier nombre que termine con " .txt "

    La opción -w : coincide solo con la palabra, por lo que Bob no coincide con Bobby , elimine esta opción si desea hacer coincidir una subcadena en el texto.

    La opción -R : buscar de forma recursiva subdirectorios, eliminar esto opción si no quieres recursión.

    Agregue la opción -i para realizar una coincidencia que no distinga mayúsculas y minúsculas. Por por defecto, fgrep distingue entre mayúsculas y minúsculas.

respondido por el jackjr300 08.08.2017 - 05:49
0

Es posible que ni siquiera necesites AppleScript. El buscador soporta búsquedas booleanas como una función avanzada. Puede guardar una búsqueda y reutilizarla o hacerla ad-hoc a medida que cambien sus necesidades.

  

Una consulta booleana utiliza AND, OR y NOT (conocidos como operadores booleanos) para restringir los resultados de búsqueda. También puede usar un signo menos (-), que significa Y NO, para excluir elementos cuando realiza una búsqueda.

Su cláusula de pedido será problemática ya que Spotlight no expone (o no considera en primer lugar) el orden de los resultados, solo que la cadena existe en el archivo.

    
respondido por el bmike 06.08.2017 - 20:29

Lea otras preguntas en las etiquetas