2 votes

Comment créer un moteur de recherche personnalisé en AppleScript

J'ai une base de données de dossiers et de fichiers (.txt) et j'essaie de créer un programme qui me permette d'entrer des mots-clés et de faire en sorte qu'il recherche ces fichiers, et qu'il produise le texte de tous les fichiers contenant les mots-clés. J'ai un code fonctionnel qui fait exactement cela, mais il ne recherche pas les mots individuellement - il recherche les mots ensemble, comme une seule chaîne de caractères.

Par exemple, si je saisis "Joe Bill Bob", j'aimerais qu'il produise des fichiers contenant chacun de ces mots n'importe où dans le fichier, même s'ils ne sont pas l'un à côté de l'autre ou dans cet ordre.

Je préférerais éviter de faire une boucle répétitive pour saisir un terme de recherche à la fois.

Je préférerais également éviter de créer des centaines de variables dans le code, et faire une boucle répétitive qui, si un caractère n'est pas un espace, l'ajoute à la première variable vide et, s'il l'est, passe à la variable suivante.

Si vous avez d'autres idées, ce serait formidable. Merci de votre compréhension.

1voto

Note : les fichiers textes doivent être encodés avec le format " UTF8 "encodage.

Voici un premier script :

Exemple : Les mots-clés :

"Bill
Bob
Joe"

fgrep y trier lignes de retour, comme ceci :

/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

Le script utilise une boucle pour vérifier le chemin de chaque élément de cette liste.

Le script récupère le chemin d'accès du premier élément, il enlève ":Bill" à la fin de la ligne --> le chemin d'accès est donc " /path/of/thisFile.txt ".

Le script vérifie l'élément (index actuel + le nombre de mots-clés -1), c'est le troisième élément, donc le troisième élément contient le même chemin, puis le script ajoute le chemin dans une nouvelle liste.

Les autres éléments ne contiennent pas tous les mots-clés.


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

Les options de fgrep :

  • En --include \"*.txt\" option : seuls les fichiers correspondant au sont recherchés, donc tous les noms qui se terminent par " .txt "

    En -w option : ne correspond qu'à un mot, donc Bob ne correspond pas Bobby , supprimez cette option si vous souhaitez faire correspondre une sous-chaîne du texte.

    En -R option : Recherche récursive dans les sous-répertoires, supprimer cette option si vous ne voulez pas de récursivité.

    Ajouter le -i pour effectuer une correspondance insensible à la casse. Par défaut par défaut, fgrep est sensible à la casse.

0voto

Oskar Points 1242

Vous n'aurez peut-être même pas besoin d'AppleScript. Finder prend en charge les recherches booléennes en tant que fonction avancée. Vous pouvez enregistrer une recherche et la réutiliser ou en créer de nouvelles en fonction de vos besoins.

Une requête booléenne utilise les opérateurs AND, OR et NOT (connus sous le nom d'opérateurs booléens) pour limiter les résultats de la recherche. Vous pouvez également utiliser le signe moins (-), qui signifie ET NON, pour exclure des éléments lors de la recherche.

Votre clause d'ordre sera problématique puisque spotlight n'expose pas (ou ne considère pas en premier lieu) l'ordre des résultats - seulement que la chaîne existe dans le fichier.

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X