Come creare un motore di ricerca personalizzato in AppleScript

2

Quindi ho un database di cartelle e file (.txt) e sto provando a creare un programma in cui posso inserire le parole chiave e farle cercare quei file, e produrrà il testo di tutti i file contenenti le parole chiave. Ho un codice funzionante che fa proprio questo, ma non cerca le parole individualmente - cerca le parole insieme, come una singola stringa.

Ad esempio, se inserisco "Joe Bill Bob", mi piacerebbe che producesse file che contengano ognuna di quelle parole in qualsiasi punto del file, anche se non si trovano l'una accanto all'altra o in quell'ordine.

Preferisco evitare di fare un ciclo ripetuto per inserire un termine di ricerca alla volta.

Preferirei anche evitare di impostare centinaia di variabili nel codice e fare un ciclo ripetuto che se un personaggio non è uno spazio lo aggiunge alla prima variabile vuota e se lo fa salta alla prossima variabile .

Se hai altre idee, sarebbe fantastico. Grazie!

    
posta DonielF 06.08.2017 - 20:17
fonte

2 risposte

1

Nota : i file di testo devono essere codificati con la codifica " UTF8 ".

Ecco uno script iniziale:

Esempio : le parole chiave:

"Bill
Bob
Joe"

fgrep e ordina righe di ritorno, come questo:

/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

Lo script usa un ciclo per controllare il percorso di ogni elemento in questo elenco.

Lo script prende il percorso dal primo elemento, rimuove ": Bill" alla fine della riga - > quindi il percorso è " /path/of/thisFile.txt ".

Lo script controlla l'elemento (indice corrente + il numero di parole chiave -1), è il terzo elemento, quindi il terzo elemento contiene lo stesso percorso, quindi lo script aggiunge il percorso in un nuovo elenco

Gli altri elementi non contengono tutte le parole chiave.

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

Le opzioni di fgrep :

  • L'opzione --include \"*.txt\" : solo i file che corrispondono al dato vengono cercati i nomi dei file, quindi qualsiasi nome che termini con " .txt "

    L'opzione -w : corrisponde solo alla parola, quindi Bob non corrisponde a Bobby , rimuovi questa opzione se vuoi abbinare una sottostringa nel testo.

    L'opzione -R : cerca ricorsivamente sottodirectory, rimuovi questo opzione se non vuoi ricorsione.

    Aggiungi l'opzione -i per eseguire la corrispondenza senza distinzione tra maiuscole e minuscole. Di predefinito, fgrep è case sensitive.

risposta data 08.08.2017 - 05:49
fonte
0

Potresti non aver nemmeno bisogno di AppleScript. Il Finder supporta le ricerche booleane come funzione avanzata. Puoi salvare una ricerca e riutilizzarla o renderla ad-hoc in base alle tue esigenze.

A Boolean query uses AND, OR, and NOT (known as Boolean operators) to narrow search results. You can also use a minus sign (–), which means AND NOT, to exclude items when you search.

La tua clausola di ordinamento sarà problematica dal momento che il riflettore non espone (o non considera sette in primo luogo) l'ordine dei risultati - solo che la stringa esiste nel file.

    
risposta data 06.08.2017 - 20:29
fonte

Leggi altre domande sui tag