Comment gérer les trémas et autres caractères de texte accentués via AppleScript


Sébastien

J'ai un problème en essayant d'exécuter des scripts shell à partir d'un script Apple. Je fais un "grep", mais dès qu'il contient des caractères spéciaux cela ne fonctionne pas comme prévu. (Le script lit une liste de sous-dossiers ob dans un répertoire et vérifie si l'un des sous-dossiers apparaît dans un fichier.)

Voici mon script :

set searchFile to "/tmp/output.txt"

set theCommand to "/usr/local/bin/pdftotext -enc UTF-8 some.pdf" & space & searchFile
do shell script theCommand

tell application "Finder"
    set companies to get name of folders of folder ("/path/" as POSIX file)
end tell

repeat with company in companies
    set theCommand to "grep -c " & quoted form of company & space & quoted form of searchFile

    try
        do shell script theCommand
        set CompanyName to company as string
        return CompanyName
    on error

    end try
end repeat

return false

Le problème est par exemple avec les chaînes avec des trémas. "theCommand" est en quelque sorte codé différemment que lorsque je le fais directement sur la CLI.

$ grep -c 'Württemberg' '/tmp/output.txt' --> typed on command line
3
$ grep -c 'Württemberg' '/tmp/output.txt' --> copy & pasted from AppleScript
0
$ grep -c 'rttemberg' '/tmp/output.txt'   --> no umlauts, no problems
3

Les « ü » de la première et de la deuxième ligne sont différents ; a le echo 'Württemberg' | openssl base64montre.

J'ai essayé plusieurs astuces d'encodage à différents endroits, essentiellement tout ce que je pouvais trouver ou penser.

Est-ce que quelqu'un a une idée? Comment puis-je vérifier l'encodage d'une chaîne ?

Merci d'avance! Sébastien

RobC

Aperçu

Cela peut fonctionner en échappant chaque caractère qui a un accent dans chaque companynom avant qu'ils ne soient utilisés dans la grepcommande.

Ainsi, vous devrez échapper chacun de ces caractères (c'est-à-dire ceux qui ont un accent) avec des doubles barres obliques inverses (c'est-à-dire \\). Par example:

  • L' üin Württembergdevra devenir\\ü
  • L' öin Königsbergdevra devenir\\ö
  • L' ßin Einbahnstraßedevra devenir\\ß

Pourquoi est-ce nécessaire :

Ces caractères accentués, comme un u avec tréma , sont certainement encodés différemment. Le type de codage qu'ils reçoivent est difficile à déterminer. Mon hypothèse est que le modèle d'encodage utilisé commence par une barre oblique inverse - c'est pourquoi l'échappement de ces caractères avec des barres obliques inverses résout le problème. Considérez le u avec tréma dans le lien précédent, cela montre que pour le langage C/C++ le üest encodé comme \u00FC.


Solution

Dans le script complet ci-dessous, vous remarquerez les éléments suivants :

  1. set accentedChars to {"ü", "ö", "ß", "á", "ė"}a été ajouté pour contenir une liste de tous les caractères qui devront être échappés. Vous devrez indiquer explicitement chacun car il ne semble pas y avoir de moyen de déduire si le personnage a un accent.
  2. Avant d'affecter la grepcommande à la theCommandvariable nous échappons d'abord les caractères nécessaires via la lecture de la ligne :

    set company to escapeChars(company, accentedChars)
    

    Comme vous pouvez le voir ici, nous passons deux arguments à la escapeCharssous-routine, (c'est-à-dire la companyvariable non échappée et la liste des caractères accentués).

  3. Dans le escapeCharssous-programme, nous parcourons chacun charde la accentedCharsliste et invoquons le findAndReplacesous-programme. Cela échappera à toutes les instances de ces caractères avec des barres obliques inverses trouvées dans la companyvariable.

Scénario complet :

set searchFile to "/tmp/output.txt"
set accentedChars to {"ü", "ö", "ß", "á", "ė"}

set theCommand to "/usr/local/bin/pdftotext -enc UTF-8 some.pdf" & ¬
  space & searchFile
do shell script theCommand

tell application "Finder"
  set companies to get name of folders of folder ("/path/" as POSIX file)
end tell

repeat with company in companies
  set company to escapeChars(company, accentedChars)

  set theCommand to "grep -c " & quoted form of company & ¬
    space & quoted form of searchFile

  try
    do shell script theCommand
    set CompanyName to company as string
    return CompanyName
  on error

  end try
end repeat

return false

(**
 * Checks each character of a given word. If any characters of the word
 * match a character in the given list of characters they will be escapd.
 *
 * @param {text} searchWord - The word to check the characters of.
 * @param {text} charactersList - List of characters to be escaped.
 * @returns {text} The new text with the item(s) replaced.
 *)
on escapeChars(searchWord, charactersList)
  repeat with char in charactersList
    set searchWord to findAndReplace(char, ("\\" & char), searchWord)
  end repeat
  return searchWord
end escapeChars

(**
 * Replaces all occurances of findString with replaceString
 *
 * @param {text} findString - The text string to find.
 * @param {text} replaceString - The replacement text string.
 * @param {text} searchInString - Text string to search.
 * @returns {text} The new text with the item(s) replaced.
 *)
on findAndReplace(findString, replaceString, searchInString)
  set oldTIDs to text item delimiters of AppleScript
  set text item delimiters of AppleScript to findString
  set searchInString to text items of searchInString
  set text item delimiters of AppleScript to replaceString
  set searchInString to "" & searchInString
  set text item delimiters of AppleScript to oldTIDs
  return searchInString
end findAndReplace

Remarque sur les comptes actuels :

Actuellement, votre modèle grep ne rapporte que le nombre de lignes sur lesquelles le mot a été trouvé. Pas combien d'instances du mot ont été trouvées.

Si vous voulez le nombre réel d'instances du mot, utilisez l' -ooption avec greppour afficher chaque occurrence. Puis dirigez-le vers wcavec la -lpossibilité de compter le nombre de lignes. Par example:

grep -o 'Württemberg' /tmp/output.txt | wc -l

et dans votre AppleScript ce serait :

set theCommand to "grep -o " & quoted form of company & space & ¬
  quoted form of searchFile & "| wc -l"

Astuce : Si vous souhaitez supprimer les espaces de début dans le compte/nombre qui est enregistré, dirigez-le vers pour supprimer sedles espaces : Par exemple via votre script :

set theCommand to "grep -o " & quoted form of company & space & ¬
  quoted form of searchFile & "| wc -l | sed -e 's/ //g'"

et l'équivalent via la ligne de commande :

grep -o 'Württemberg' /tmp/output.txt | wc -l | sed -e 's/ //g'

Articles connexes


Comment gérer les caractères accentués en python?

Zeno Dalla Valle Je sais qu'il y a beaucoup de matériel à ce sujet, mais je ne peux pas trouver de solution à mon problème. J'ai ce texte écrit dans un fichier txt que je dois manipuler, etc. et il contient beaucoup de caractères accentués. Je ne peux pas les

tesseract - comment gérer les séparateurs de caractères

jackluo923 Comment gérer la reconnaissance du texte à l'intérieur des séparateurs de caractères avec tesseract (pré-traitement ou via une configuration tesseract spéciale) de manière appropriée, en particulier le type en peigne (3e image), comme dans ces trois