Benutzer-Werkzeuge

Webseiten-Werkzeuge


zeichensaetze_konvertieren

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
zeichensaetze_konvertieren [2013-10-18 12:40:17] manfredzeichensaetze_konvertieren [2024-11-22 10:07:25] (aktuell) – [dos2unix] manfred
Zeile 1: Zeile 1:
 +====== Zeichensätze konvertieren ======
 +
 +Siehe auch [[Dateiformate konvertieren]] und [[Byte Order Mark - BOM]]
 +
 +  * [[http://wiki.ubuntuusers.de/Zeichensatz-Konverter]]
 +
 +
 +==== convmv ====
 +
 +Dieses Werkzeug dient zur Umwandlung von Dateinamen.
 +
 +
 +==== sed ====
 +
 +DOS-Zeilenenden zu Unix-Zeilenenden umwandeln:
 +  > sed -i 's/\x0D$//' DATEI 
 +
 +Unix-Zeilenenden zu DOS-Zeilenenden umwandeln:
 +  > sed -i 's/$/\r/' DATEI
 +
 +
 +==== dos2unix ====
 +
 +Wenn man unter DOS/Windows eine Textdatei erstellt, dann enthält sie am Zeilenende das //^M//-Zeichen.
 +Um es zu entfernen, kann man im einfachsten Fall das folgende Kommando ausführen:
 +  # tr -d \\r < dosfile > newfile
 +  # cat dosfile | tr -d '\r' > newfile
 +
 +Es ist aber auch möglich den Befehl "dos2unix" zu verwenden und für die umgekehrte Umwandlung den Befehl "unix2dos".
 +
 +Installiert werden diese Befehle in **FreeBSD** mit:
 +  # portinstall -prO converters/dosunix
 +  # pkg install dosunix
 +  # pkg install dos2unix
 +
 +Installiert werden diese Befehle in **Ubuntu** mit:
 +  # apt install dos2unix
 +
 +Datei in **FreeBSD** vom DOS-Format ins Unix-Format überführen:
 +  # dosunix datei
 +
 +Datei in **FreeBSD** vom Unix-Format ins DOS-Format überführen:
 +  # unixdos datei
 +
 +Installiert werden diese Befehle in **Ubuntu** mit:
 +  # apt install tofrodos
 +
 +Datei in **Ubuntu** vom DOS-Format ins Unix-Format überführen:
 +  # fromdos datei
 +
 +Datei in **Ubuntu** vom Unix-Format ins DOS-Format überführen:
 +  # todos datei
 +
 +
 +==== iconv ====
 +
 +**''iconv''** ist der Klassiker, er beherscht praktisch alle Zeichensätze mit denen man in Kontakt kommen könnte und erlaubt das konvertieren von einem beliebigen in einen beliebigen Zeichensatz:
 +  > iconv -f ISO-8859-15 -t UTF-8 -o utf8datei.txt isodatei.txt
 +
 +Mir ist leider kein Werkzeug bekannt, mit dem man automatisch in einem Skript, den verwendeten Zeichensatz in einer Datei erkennen kann.
 +
 +Aber glücklicherweise gibt **''iconv''** immer dann eine Warnung aus, wenn es ein oder mehrere Zeichen nicht sinnvoll konvertieren konnte.
 +Mit diesem Wissen kann man sich einen Zeichensatzdetektor (für die relevanten Fälle) selber bauen, der allerdings nur erkennen kann, welcher Zeichensatz überhauptnicht passen kann.
 +
 +In diesem Beispiel wollen wir als Ergebnis ein Datei im UTF8-Format haben und wir wissen, wenn sie nicht in der UTF8-Kodierung vorliegt, dann liegt sie in der ISO-8859-1-Kodierung vor.
 +Einen "echten" Universal-Detektor können wir so leider nicht bauen.
 +
 +hier probieren wir die beiden bekannten Zeichensatzkodierungen an einer ISO-8859-1 kodierten Datei aus:
 +  > cat /tmp/test_iso88591.txt | iconv -f ISO-8859-1 -t UTF-8 | wc
 +      167     371    4273
 +  
 +  > cat /tmp/test_iso88591.txt | iconv -f UTF-8 -t UTF-8 | wc
 +  iconv: ungültige Eingabe-Sequenz an der Stelle 119
 +       11           119
 +  
 +  > cat /tmp/test_iso88591.txt | iconv -f ISO-8859-1 -t UTF-8 | wc -m
 +  4194
 +  
 +  > cat /tmp/test_iso88591.txt | iconv -f UTF-8 -t UTF-8 | wc -m
 +  iconv: ungültige Eingabe-Sequenz an der Stelle 119
 +  119
 +
 +Kodekombinationen, die garnicht funktionieren weil sie unkültige Zeichen erzeugen würden und somit ausgeschlossen werden können, äußern sich hier mit einer Fehlermeldung.
 +
 +hier probieren wir die beiden bekannten Zeichensatzkodierungen an einer UTF-8 kodierten Datei aus:
 +  > cat /tmp/test_utf8.txt | iconv -f ISO-8859-1 -t UTF-8 | wc
 +      168     371    4265
 +  
 +  > cat /tmp/test_utf8.txt | iconv -f UTF-8 -t UTF-8 | wc
 +      168     371    4107
 +  
 +  > cat /tmp/test_utf8.txt | iconv -f ISO-8859-1 -t UTF-8 | wc -m
 +  4107
 +  
 +  > cat /tmp/test_utf8.txt | iconv -f UTF-8 -t UTF-8 | wc -m
 +  4028
 +
 +Hier gibt es keine Fehlermeldungen und so müssen wir die Dateilänge in Byte oder Zeichen messen.
 +__Richtig ist hier die kleinere Zahl, weil die Sonderzeichen im UTF-8-Zeichensatz doppelt so lang sind, wie im ISO-8859-1-Zeichensatz.__
 +
 +Ein "ä" belegt auf der Festplatte in UTF-8 kodiert, 16 Byte.
 +Werden also diese 16 Byte mit ISO-8859-1 dekodiert, müssen zwei Zeichen dabei rauskommen.
 +
 +
 +=== Zeichensatzkodierung per Skript erkennen ===
 +
 +  * [[http://wiki.ubuntuusers.de/Skripte/Zeichensatzkonvertierung#Bash]]
 +
 +Es ist aber möglich eine zutreffende Zeichensatzkodierung zu finden, wenn man ein Wort mit Sonderzeichen aus der entsprechenden Datei kennt.
 +Dann kann man einfach alle Zeichensatzkodierungen durchprobieren, bis das Wort mit Sonderzeichen richtig lesbar ist.
 +Genau das wird in dem folgenden Skript getan.
 +
 +<file>
 +#!/bin/bash
 +#
 +# encoding-finder.sh
 +# (C) GPLv3, Stefan Wagner 2007
 +#
 +###
 +### In einer Datei einen bekannten (Teil-)String (z.B.: Begrüßung) suchen,
 +### indem alle Encodings ausprobiert werden.
 +###
 +#
 +# angepasst von Manfred Heins am 18. Okt. 2013
 +# so das nur die ISO-8859-, UTF- und WINDOWS-Zeichensatzkodierungen ausprobiert werden
 +#
 +[[ $# -ne 2 ]] && echo "Usage: ${0} DATEINAME PATTERN_MIT_UMLAUT_DER_SICHER_IN_DATEI_IST" && exit
 +FILE="${1}"
 +PATTERN="${2}"
 +for enc in $( iconv -l | sed 's/..$//' | egrep '8859-|UTF|WINDOWS')
 +do
 +        iconv -f "${enc}" -t UTF-8 "${FILE}" 2>/dev/null | fgrep "${PATTERN}" >/dev/null && echo "${enc}"
 +done | head -n1
 +</file>
 +
 +Hier werden allerdings nur die gebräuchlichen ISO-8859- und UTF-Zeichensatzkodierungen ausprobiert und nur der erste Treffer wird ausgegeben, das ist für die automatische Verwendung in Skripten besser geeignet.
 +
 +
 +==== Zeichensatz_konvertieren_nach_UTF8 ====
 +
 +  > vi Zeichensatz_konvertieren_nach_UTF8.sh
 +<file>
 +#!/usr/bin/env bash
 +
 +#
 +# Dieses Skript konvertiert alle Dateien in einen anderen Zeichensatz,
 +# dessen Inhalt erst den angegeben Pattern enthält, wenn er konvertiert wurde.
 +# Der richtige Zeichensatz wird dabei durch ausprobieren ermittelt.
 +# Es werden hier aber NICHT alle möglichen Zeichensätze ausprobiert,
 +# so das nur die ISO-8859-, UTF- und WINDOWS-Zeichensatzkodierungen ausprobiert werden
 +#
 +# Meine Inspiration für dieses Skript habe ich von hier:
 +# http://wiki.ubuntuusers.de/Skripte/Zeichensatzkonvertierung#Bash
 +#
 +VERSION="v2013102100"
 +
 +### Hilfe
 +[[ $# -ne 2 ]] && echo "Usage: ${0} DATEINAME PATTERN_MIT_UMLAUT_DER_SICHER_IN_DATEI_IST" && exit
 +
 +### alle brauchbaren Zeichensatzkodierungen ermitteln
 +DATEIPFAD="${1}"
 +PATTERN="${2}"
 +DATEIVERZ="$(dirname "${DATEIPFAD}")"
 +DATEINAME="$(basename "${DATEIPFAD}")"
 +cd ${DATEIVERZ}/ || exit 1
 +ZEICHENSATZKODIERUNGEN="$(for enc in $(iconv -l | sed 's/..$//' | egrep -i '8859-|UTF|WINDOWS')
 +do
 +        iconv -f "${enc}" -t UTF-8 "${DATEINAME}" 2>/dev/null | fgrep "${PATTERN}" >/dev/null && echo "${enc}"
 +done)"
 +
 +#------------------------------------------------------------------------------#
 +### weitere Tests
 +
 +### Werte für den Plausibilitätstest generieren
 +AUSGABE="$(
 +for KODIERUNG in ${ZEICHENSATZKODIERUNGEN}
 +do
 +        if [ "${KODIERUNG}" != "UTF-8" -a "${KODIERUNG}" != "UTF8" ] ; then
 +                DEKODIERTERINHALT="$(iconv -f ${KODIERUNG} -t UTF-8 ${DATEINAME} 2>/dev/null)"
 +                if [ "${?}" == "0" ] ; then
 +                        ZEICHENANZAHL="$(echo "${DEKODIERTERINHALT}" | wc -m)"
 +                        echo "${ZEICHENANZAHL} ${KODIERUNG}" #>/dev/null
 +                else
 +                        echo "'${KODIERUNG}'" >/dev/null
 +                fi
 +        else
 +                echo "'${KODIERUNG}': Die Datei ist bereits in UTF-8 kodiert." >/dev/null
 +        fi
 +done
 +)"
 +
 +### Plausibilitätstest ermittelt die passenste Zeichensatzkodierung
 +TREFFER="$(echo "${AUSGABE}" | awk '{print $1}' | sort -n | head -n1)"
 +QUELLZS="$(echo "${AUSGABE}" | egrep "^${TREFFER} " | awk '{print $2}' | head -n1)"
 +
 +### Konvertierung
 +if [ -n "${QUELLZS}" ] ; then
 +        iconv -f ${QUELLZS} -t UTF-8 -o neu_utf8.txt ${DATEINAME} && (sed -i 's/[Ii][Ss][Oo][-_]*8859[-][0-9][0-9]*[Ee]*[:]*[0-9]*/UTF-8/g' neu_utf8.txt;mv -v ${DATEINAME} ${DATEINAME}_$(date +'%Y%m%d%H%M%S') && mv -v neu_utf8.txt ${DATEINAME})
 +fi
 +</file>
 +
 +Wenn wir beispielsweise zwei Dateien nehmen, eine dessen Inhalt ISO-8859-1 kodiert ist und eine, die UTF-8 kodiert ist:
 +  > ls -lh
 +  -rw-r--r-- 1 fritz fritz 4,1K Okt 18 12:18 test_iso88591.txt
 +  -rw-r--r-- 1 fritz fritz 4,1K Okt 18 12:18 test_utf8.txt
 +
 +Dann wird von diesem Skript nur die ISO-8859-1 kodierte Datei konvertiert:
 +  > ./Zeichensatz_konvertieren_nach_UTF8.sh test_iso88591.txt 'Begrüßung'
 +  "test_iso88591.txt" -> "test_iso88591.txt_20131018165849"
 +  "neu_utf8.txt" -> "test_iso88591.txt"
 +  
 +  > ./Zeichensatz_konvertieren_nach_UTF8.sh test_utf8.txt 'Begrüßung'
 +  
 +  > ls -lh
 +  -rw-r--r-- 1 fritz fritz 4,2K Okt 18 16:58 test_iso88591.txt
 +  -rw-r--r-- 1 fritz fritz 4,1K Okt 18 12:18 test_iso88591.txt_20131018165849
 +  -rw-r--r-- 1 fritz fritz 4,1K Okt 18 12:18 test_utf8.txt
 +