Mam plik w kodowaniu UTF-8 z BOM i chcę usunąć BOM. Czy istnieją jakieś narzędzia wiersza polecenia systemu Linux do usunięcia BOM z pliku?
$ file test.xml
test.xml: XML 1.0 document, UTF-8 Unicode (with BOM) text, with very long lines
Mam plik w kodowaniu UTF-8 z BOM i chcę usunąć BOM. Czy istnieją jakieś narzędzia wiersza polecenia systemu Linux do usunięcia BOM z pliku?
$ file test.xml
test.xml: XML 1.0 document, UTF-8 Unicode (with BOM) text, with very long lines
Odpowiedzi:
Jeśli nie masz pewności, czy plik zawiera BOM UTF-8, to (przy założeniu implementacji GNU sed
) usunie BOM, jeśli istnieje, lub nie wprowadzi żadnych zmian, jeśli nie będzie.
sed '1s/^\xEF\xBB\xBF//' < orig.txt > new.txt
Możesz również zastąpić istniejący plik -i
opcją:
sed -i '1s/^\xEF\xBB\xBF//' orig.txt
en_US.UTF-8
ustawieniami regionalnymi i działało. Kiedy to zawiedzie?
-<U+FEFF>\chapter{xxx}
Po: +\chapter{xxx}^M
Objaśnienie: Używanie słowa MS do literówek w pliku lateksu. Lateks pod Linuksem pokazuje wspomniane błędy. Dane wyjściowe pochodzą z systemu git. Jak mogę zmienić wyrażenie, aby uchwycić ten szczególny przypadek?
LM nie ma sensu w UTF-8. Są one zazwyczaj dodawane przez pomyłkę przez fałszywe oprogramowanie w systemach operacyjnych Microsoft.
dos2unix
usunie go, a także zadba o inne osobliwości plików tekstowych Windows.
dos2unix test.xml
dos2unix
?
Możliwe jest usunięcie BOM z pliku za pomocą tail
polecenia:
tail -c +4 withBOM.txt > withoutBOM.txt
tail
używa indeksowania opartego na 1 ?! WTF!
tail -c -1
lub tail -c 1
(co tail
jest zwykle używane) to treść zaczynająca się od ostatniego bajtu, tail -c +1
zaczynająca się od pierwszego bajtu. tail -c 0
/ tail -c +0
ponieważ byłoby to o wiele bardziej nieintuicyjne.
(dd bs=1 count=3 of=/dev/null; cat) <input >output
. Lub z GNU (head -c3 >/dev/null; cat)
- nawet w UTF8 lub innych ustawieniach narodowych innych niż jednobajtowe; GNU head robi „char” = bajt.
Otwórz plik w VIM:
vi text.xml
Usuń kodowanie BOM:
:set nobomb
Zapisz i wyjdź:
:wq
<feff>
, ale :set nobomb
go nie modyfikuje ani nie usuwa.
Możesz użyć
LANG=C LC_ALL=C sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- filename
aby usunąć znak kolejności bajtów z początku pliku, jeśli taki istnieje, a także przekonwertować dowolne nowe wiersze CR LF tylko na LF. LANG=C LC_ALL=C
Mówi powłoce chcesz polecenie do uruchomienia w lokalizacji domyślnej C (znany również jako domyślna POSIX locale), gdzie trzy bajty tworzące Byte Order Mark traktowane są jako bajty. -i
Opcja sed znaczy w miejscu. Jeśli używasz -i.old
, to sed zapisuje oryginalny plik jako filename.old
, a nowy plik (z ewentualnymi modyfikacjami) jako filename
.
Osobiście lubię to mieć jako ~/bin/fix-ms
; na przykład jako
#!/bin/dash
export LANG=C LC_ALL=C
if [ $# -gt 0 ]; then
for FILE in "$@" ; do
sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- "$FILE" || exit 1
done
else
exec sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//'
fi
więc jeśli muszę to zastosować, aby powiedzieć wszystkie pliki źródłowe C i nagłówki (na przykład mój stary kod z ery MS-DOS!), po prostu uruchamiam
find . -name '*.[CHch]' -print0 | xargs -r0 ~/bin/ms-fix
lub, jeśli chcę tylko spojrzeć na taki plik, bez modyfikacji, mogę uruchomić
~/bin/ms-fix < filename | less
i nie widzę brzydkiego <U+FEFF>
w moim terminalu UTF-8.
sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- "$@"
?
sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- "$@"
nie działa; zwraca kod wyjścia, ale przed wyjściem przetwarza wszystkie pliki wymienione na liście argumentów.
--
Przed nazwami plików jest oczywiście ważne: bez nich nazwy plików zaczynające się od myślnika mogą być uważane za opcje przez sed. Zredagowałem je w mojej odpowiedzi; dziekuje za przypomnienie!
Niedawno znalazłem to małe narzędzie wiersza polecenia, które dodaje lub usuwa BOM w dowolnych plikach zakodowanych w UTF-8: UTF BOM Utils ( nowy link na github)
Mała wada, możesz pobrać tylko zwykły kod źródłowy C ++. Musisz utworzyć plik makefile ( na przykład z CMake ) i skompilować go samodzielnie, na tej stronie nie ma plików binarnych.