2010-06-27 11 views
28

Ich suche (ohne Erfolg) ein Skript, das als Batch-Datei funktionieren und mir erlauben würde, eine UTF-8-Textdatei mit einer Stückliste voranzustellen, wenn sie keine hat.Hinzufügen von Stücklisten zu UTF-8-Dateien

Weder die Sprache, in der es geschrieben ist (Perl, Python, C, Bash) noch das Betriebssystem, auf dem es arbeitet, sind für mich wichtig. Ich habe Zugriff auf eine Vielzahl von Computern.

Ich habe eine Menge Skript gefunden, um das Gegenteil zu tun (strip the BOM), das klingt für mich irgendwie albern, wie viele Windows-Programm Probleme beim Lesen von UTF-8 Textdateien haben, wenn sie nicht haben eine Stückliste

Habe ich das Offensichtliche vermisst? Danke!

Antwort

4

Ich finde es ziemlich einfach. Unter der Annahme, die Datei ist immer UTF-8 (Sie nicht die Codierung zu erfassen, Sie die Codierung wissen):

Lesen Sie die ersten drei Zeichen. Vergleichen Sie sie mit der UTF-8-BOM-Sequenz (Wikipedia sagt, es ist 0xEF, 0xBB, 0xBF). Wenn es gleich ist, drucken Sie sie in der neuen Datei und kopieren Sie dann alles andere von der ursprünglichen Datei in die neue Datei. Wenn es anders ist, drucken Sie zuerst die Stückliste, dann drucken Sie die drei Zeichen und nur dann drucken Sie alles andere aus der Originaldatei in die neue Datei.

In C sollte fopen/fclose/fread/fwrite ausreichen.

39

Ich schrieb diese addbom.sh mit dem 'Datei' Befehl und ICU 's' Uconv 'Befehl.

#!/bin/sh 

if [ $# -eq 0 ] 
then 
     echo usage $0 files ... 
     exit 1 
fi 

for file in "[email protected]" 
do 
     echo "# Processing: $file" 1>&2 
     if [ ! -f "$file" ] 
     then 
       echo Not a file: "$file" 1>&2 
       exit 1 
     fi 
     TYPE=`file - < "$file" | cut -d: -f2` 
     if echo "$TYPE" | grep -q '(with BOM)' 
     then 
       echo "# $file already has BOM, skipping." 1>&2 
     else 
       (mv "${file}" "${file}"~ && uconv -f utf-8 -t utf-8 --add-signature < "${file}~" > "${file}") || (echo Error processing "$file" 1>&2 ; exit 1) 
     fi 
done 

edit: Hinzugefügt Anführungszeichen um die mv Argumente. Danke @DirkR und froh, dass dieses Skript so hilfreich war!

+1

Absolut perfekt! Viel besser als das, womit ich gekommen bin. Vielen Dank. – Stephane

+2

"$ @" ist hier besser als $ *. Dies wird Argumente mit Leerzeichen (nützlich auf Windows + Cygwin) – mcoolive

+0

@mcoolive Dank –

0

Ich dachte, ich werde nicht so eine triviale Sache selbst zu schreiben, aber da ich auch einige charset Konvertierung erforderlich zu tun, hier ist es:

#!/usr/bin/python 
import os 
import sys 
import codecs 

INPUT_ENCODING = codecs.BOM_UTF16_LE # 'utf_16_le' 
OUTPUT_ENCODING = 'utf-8-sig'   # is there a constant for this?? 

if len(sys.argv) == 1: 
    print 'Usage:\n\t%s <filename.txt>' % sys.argv[0] 
    sys.exit(-1) 

output_file = os.path.splitext(os.path.split(sys.argv[1])[-1])[0] 
fin = codecs.open(sys.argv[1], 'rb', encoding=INPUT_ENCODING) 
fout = codecs.open(output_file + '_utf8bom.txt', 'wb', encoding=OUTPUT_ENCODING) 
fout.write(fin.read()) 
fin.close() 
fout.close() 

print 'done' 

Nennen Sie es, mit dem der ursprünglichen Dateinamen nur , das heißt:

# utf8bom_add.py myfilename.txt 

Und wenn Sie UTF-8-UTF-8 konvertieren sie die INPUT_ENCODING auf den richtigen Wert ändern.

10

(Antwort basierend auf https://stackoverflow.com/a/9815107/1260896 von yingted)

Um Stücklisten zu allen Dateien hinzufügen, die mit „foo-“ starten, können Sie sed verwenden. sed verfügt über eine Option zum Erstellen einer Sicherung.

sed -i '1s/^\(\xef\xbb\xbf\)\?/\xef\xbb\xbf/' foo-* 

Wenn Sie sicher wissen, gibt es bereits keine BOM, können Sie den Befehl vereinfachen:

sed -i '1s/^/\xef\xbb\xbf/' foo-* 

Stellen Sie sicher, UTF-8, festlegen müssen, weil zB UTF-16 unterscheidet (anders How can I re-add a unicode byte order marker in linux?) überprüfen

+1

Für UTF-8 verwenden Sie '\ xef \ xbb \ xbf'; für UTF-16 Little-Endian verwenden '\ xff \ xfe'; Verwenden Sie für UTF-16-Big-Endian '\ xfe \ xff'. Siehe https://www.w3.org/International/questions/qa-byte-order-mark –

+0

Das hat bei mir nicht funktioniert. Die Befehlszeile 'sed -i '1s/^/\ xef \ xbb \ xbf /' temp.csv 'gab mir' sed: 1: "temp.csv": undefinierte Bezeichnung' emp.csv'' –

+0

@PerLundberg konnte man versuche, Fehler zu beheben .. probiere 'sed' 1s/asdfasdfasdf // 'blah.csv' Das Fehlen von -i macht es sehr sicher, weil es die Eingabedatei unverändert lässt und das Ergebnis an die Konsole ausgibt. Diese Zeile sollte in Zeile eins suchen, nach der Zeichenfolge asdfasdfasdf suchen und sie durch nichts ersetzen, d. H. Diese Zeichenfolge löschen. Dann versuche es zu machen '^ adsfasdfsdf' Das'^'markiert den Anfang der Zeile, vielleicht verursacht das das Problem aus irgendeinem Grund. Vielleicht müssen Sie einen Schalter mit sed verwenden, um es zu benutzen, um das '^' wie vielleicht zu verwenden-E, obwohl ich nicht weiß. – barlop

15

Der einfachste Weg, die ich für diese gefunden ist

#!/usr/bin/env bash 

#Add BOM to the new file 
printf '\xEF\xBB\xBF' > with_bom.txt 

# Append the content of the source file to the new file 
cat source_file.txt >> with_bom.txt 

ich es wissen verwendet ein externes Programm (cat) ... aber es wird die Arbeit leicht in bash

Getestet auf osx sollte aber auf Linux arbeitet auch

Hinweis, dass es davon ausgeht, dass die Datei nicht bereits BOM tun (!)