2012-07-17 5 views
2

Je veux convertir la sortie de n'importe quel site Web obtenu avec curl en utf8 pour une insertion de base de données.Convertir stdout à utf8 en bash

utilisation ex:

html="$(curl -iL -compressed "$link")" 

##code needed to convert nonUTF8 $html to utf8, preferably without writing to file 

## escape characters for insert 
html_q="${html//'\'/\\\\}" 
html_q="${html_q//"'"/\'}" 

## the insert statement 
sqlHtml='INSERT INTO `'"${tableHtml}"'` (`html`) VALUES ('"'${html_q}'"');' 
mysql -u$dbUser -p$dbPass -h$dbHost -P$dbPort -D$dbName --default_character_set utf8 -A <<ENDofMESSAGE 
${sqlHtml} 
ENDofMESSAGE 
+0

Comment vous attendez-vous à déterminer quel est le jeu de caractères des données dans '$ html'? Vous ne pouvez pas convertir les déchets aléatoires en UTF-8 et vous attendre à ce que le résultat soit raisonnable, vous devez savoir de quel jeu de caractères vous convertissez. – cdhowie

+0

probablement en utilisant l'en-tête de curl, comme http://stackoverflow.com/questions/2510868/php-convert-curl-exec-output-to-utf8 –

+0

Eh bien, c'est bash et pas PHP. Je ne suis pas sûr que le client de ligne de commande curl vous donne un accès facile à cet en-tête. Vous pourriez envisager d'écrire ceci en Python - voir [cette réponse] (http://stackoverflow.com/a/3683863/501250) pour une solution possible. – cdhowie

Répondre

6

question courte, réponse courte:

man iconv

Maintenant, vous avez un autre problème: déterminer ce qui est le codage source de votre page Web. (astuce: tapez charsetdetector dans google)

+0

Peut-iconv le faire depuis stdout? et pas d'un fichier? –

+1

Vous voulez dire de stdin? Si oui, oui. Juste tuyau votre contenu. quel que soit | iconv -fSOURCE_ENCODING -tDEST_ENCODING' – Scharron

0

Cela ne peut pas être fait correctement sans un analyseur dans le cas général. Les scripts ne le couperont pas. Si votre objectif est de stocker la page, traitez-la comme binaire, compressez et convertissez en un formulaire imprimable.

+0

définir 'parser', donner un exemple. Dans mon problème, je voudrais imiter les sorties du navigateur, utiliser cet algorithme pour spécifier l'encodage et le convertir en utf8. –

+0

aussi si je le stocke comme binaire comment je chercherais à travers si je ne connais pas l'encodage? –

+0

logiciels qui comprennent la syntaxe html qui peut séparer html en différents éléments properl, navigateur Web a un, vous ne connaissez pas le codage de la page, sauf si vous regardez l'en-tête de contenu http et/ou la méta-tag du html, – pizza

0

Voici la solution que je suis allé pour:

#!/bin/bash 

result="$({ stdout="$(curl -Lsv -compressed "$1")" ; } 2>&1; echo "--SePaRaToR--"; echo "$stdout")"; 
echo ' 
found:' 
echo "$result" | grep -o '\(charset\|encoding\)[ ]*=[ ]*["]*[a-zA-Z0-9_: -]*' 
echo ' ' 
status=1 
charset="ISO_8859-1" #set default 
# 1: HTTP Content-Type: header 
# 2: <meta> element in the page 
# 3: <xml> element in the page 
regex='.*(charset|encoding)\s*=\s*["]*([a-zA-Z0-9_: -]*)' 
if [[ "$result" =~ $regex ]] 
    then 
     charset="${BASH_REMATCH[2]}"  
     status=2 
     echo "match succes: $charset" 
    else 
     echo "match fail: $charset : ${BASH_REMATCH[2]}" 
fi 


if [[ "$charset" == *utf-8* || "$charset" == *UTF-8* ]] 
    then 
     charset='NotModified' 
    else 
    echo "iconv '$charset' to UTF-8//TRANSLIT" 
    html=$(echo "$result" | iconv -f"$charset" -t'UTF-8//TRANSLIT') 
    if [ $? -ne 0 ] 
     then 
     echo "translit failed : iconv '$charset' to UTF-8//IGNORE" 
     html=$(echo "$result" | iconv -f"$charset" -t"UTF-8//IGNORE") 
     if [ $? -ne 0 ] 
      then    
      charset="ISO_8859-1" 
      echo "ignore failed : iconv '$charset' to UTF-8//IGNORE" 
      html=$(echo "$result" | iconv -f"$charset" -t"UTF-8//IGNORE") 
      status=4 
     fi 
     status=3 
    fi 

fi 
echo "charset: '$charset' , status: '$status'" 

La valeur par défaut est le w3c recomandation.
Ce n'est pas 100% précis mais c'est rapide et il fera son travail 99% du temps.

Espérons que cela aide quelqu'un dans la même situation.
Merci aussi à tous ceux qui ont répondu.

+0

s'il n'y a pas de 1,2,3 dans la page, et qu'il y a un contenu de données, c'est-à-dire "" alors la commande iconv échouera. Ne voulez-vous pas limiter le résultat $ à un sous-ensemble valide acceptable? – pizza

+0

Je pourrais ajouter quelque chose comme: 'IF [" $ {BASH_REMATCH [2]} "dans $ (iconv --list)] puis charset =" $ {BASH_REMATCH [2]} "; sinon laisser par défaut ou essayer la correspondance précédente; fi' mais cela ralentirait le processus, et j'ai besoin de scanner plus de 100k domaines/jour. Je vais gérer ces erreurs en post-traitement et les re-scanner ensuite avec un algorithme plus lourd. –

+0

de toute façon @pizza merci pour la capture. –