BOM'yi UTF-8 dosyasından nasıl kaldırabilirim?


63

UTF-8'de BOM kodlayan bir dosyam var ve BOM'u kaldırmak istiyorum. Malzeme Listesini dosyadan kaldırmak için herhangi bir linux komut satırı aracı var mı?

$ file test.xml
test.xml:  XML 1.0 document, UTF-8 Unicode (with BOM) text, with very long lines


1
Bunu birkaç ay önce yapmak için oldukça basit bir araç yaptım: oskog97.com/read/?path=/small-scripts/killbom&referer=/… / usr / local / bin dizinine benzer bir şey kurmaya değer olabilir BOM'lar ile kodlanmış birçok UTF-8 dosyanız var.
Oskar Skog

Yanıtlar:


76

Eğer dosyanın UTF-8 BOM içerip içermediğinden emin değilseniz, o zaman bu (GNU uygulamasının varsayıldığı varsayılarak sed) varsa BOM silinecektir veya yoksa değişiklik yapılmayacaktır.

sed '1s/^\xEF\xBB\xBF//' < orig.txt > new.txt

-iSeçenekle birlikte mevcut dosyanın üzerine de yazabilirsiniz :

sed -i '1s/^\xEF\xBB\xBF//' orig.txt

4
bu utf8 yerel ayarında çalışmayabilir, ancak c veya posix'e yerel ayar geçersiz kılmaları hazırlamak her zaman işe yarar.
hildred

3
@hildred en_US.UTF-8Yerel ayarlarla test ettim ve çalıştı. Ne zaman başarısız olacak?
m13r

2
@ m13r, sed ve derleme seçeneklerinin sürümüne bağlıdır. Başarısızlık durumunda, Unicode karakter sınıflarına sahip çok yeni bir sed sürümü, üç bayt sırasını, üç karakter sırasına uymayan tek bir karakter olarak getirecektir. Ancak bu durumda on altı bitlik bir karakter eşleştirmesi yapabilirsiniz. Ancak bu yeni bir özelliktir ve evrensel olarak mevcut değildir. Test etmek istiyorsanız en son sürümü derlemenizi tavsiye ederim.
hildred

4
Unicode etkin bir sed ile çalışmasını sağlamak için LC_ALL = C sed '1s / ^ \ xEF \ xBB \ xBF //' yapın
Joshua

1
@mazunki, 1s/yalnızca ilk satırı ara anlamına gelir; diğer çizgiler etkilenmez. ^Araçlar sadece (birinci) satırın başında eşleşir. \xEF\xBB\xBFUTF-8 ürün reçetesidir (kaçan hex string). //hiçbir şey ile değiştirmek anlamına gelir. I ilave olabilir 1ucuna (talimat için 1s/^xEF\xBB\xBF//1, sadece ortalama hat üzerindeki desenin ilk geçtiği eşleşecektir). Ancak, arama bağlantılı olduğu için ^, bu herhangi bir fark yaratmayacaktır. Dosya ilk satırın başında BOM'a sahip değilse, desen eşleşmez ve bu nedenle değişiklik yapılmaz.
CSM

64

Bir malzeme listesi UTF-8'de bir anlam ifade etmiyor. Bunlar genellikle Microsoft işletim sistemlerinde sahte yazılım tarafından yanlışlıkla eklenir.

dos2unix onu kaldıracak ve aynı zamanda Windows metin dosyalarının diğer özelliklerine de dikkat edecektir.

dos2unix test.xml

17
UTF-8 kodlu bir malzeme listesinin bir anlam ifade etmediğini kabul ediyorum, ancak ister inan ister inanma, UTF-8'i diğer 8 bit kodlamalardan ayırt etmenin harika bir fikir olduğunu düşünen birçok insan var. Yani bu bir zevk meselesi. Windows Notepad bilerek bir malzeme listesi ekler.
Johan Myréen

17
Bağlamın nasıl kaldırılacağı ile ilgili bir soru olduğu zaman, anlam ifade edip etmemesi ne önemlidir? Wikipedia'ya göre Not Defteri, BOM'un bir dosyayı UTF-8 olarak tanımasını gerektirir ve Google Dokümanlar da bir dosyayı metin olarak dışa aktarırken ekler. Hepsinin yanlışlıkla yaptıklarından şüpheliyim .
ilkkachu

Yorumlar genişletilmiş tartışmalar için değildir; bu konuşma sohbete taşındı .
terdon

1
Satır sonlarını dönüştürmemek ve malzeme listesini birlikte kaldırmak için bir yol var mı dos2unix?
m13r

2
@ m13r Daha sonra bu cevaptaki sed betiğini kullanın . Bu sadece bomu kaldıracak (eğer varsa), başka hiçbir şey değişmeyecek.
Arrow

25

Malzeme Listesini şu tailkomutla bir dosyadan çıkarmak mümkündür :

tail -c +4 withBOM.txt > withoutBOM.txt

2
Neden 4 Malzeme Listesi 3 byte'a sahiptir.
deviantfan

10
@deviantfan Bu yüzden atlamak istiyorsanız 4. bayta başlamalısınız.
Stéphane Chazelas

9
tail1 tabanlı indeksleme kullanıyor mu ?! O NE LAN!
CodesInChaos

5
@CodesInChaos tail -c -1veya tail -c 1( tailgenellikle ne için kullanılır) tail -c +1ilk bayt ile başlayan , son bayt ile başlayan içeriktir . tail -c 0Bunun tail -c +0için çok daha sezgisel olmazdı.
Stéphane Chazelas

2
@deviantfan: (dd bs=1 count=3 of=/dev/null; cat) <input >output. Veya GNU ile (head -c3 >/dev/null; cat)- UTF8 veya diğer tekbayt olmayan yerel ayarlarda bile; GNU başkanı 'char' = bayt yapar.
dave_thompson_085

20

VIM Kullanımı

  1. Dosyayı VIM'de aç:

    vi text.xml
    
  2. BOM kodlamasını kaldırın:

    :set nobomb
    
  3. Kaydet ve çık:

    :wq
    

Tuhaf bir şekilde bir mac üzerindeki vim 8 ile Excel tarafından yapılan bir csv utf-8 dosyası var ve başlıyor <feff>, ancak :set nobombonu değiştirmiyor veya kaldırmıyor.
dlamblin

5

Kullanabilirsiniz

LANG=C LC_ALL=C sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- filename

Herhangi bir CR LF yeni satırını sadece LF'ye dönüştürmenin yanı sıra, bayt sıra işaretini dosyanın başından kaldırmak için varsa. LANG=C LC_ALL=CKomut Bayt al Mark oluşturan üç bayt bayt olarak kabul edilir (ayrıca varsayılan POSIX yerelinde olarak da bilinir) varsayılan C yerelinde, çalışmasını istediğiniz kabuk söyler. -iSed seçeneği yerinde demektir. Eğer kullanırsanız -i.old, o zaman sed gibi orijinal dosyayı kaydeder filename.oldolarak (varsa, değişikliklerle) ve yeni bir dosya filename.


Şahsen buna sahip olmayı seviyorum ~/bin/fix-ms; örneğin,

#!/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

bu nedenle, tüm C kaynak dosya ve başlıklarını (örneğin, MS-DOS dönemindeki eski kodum!) söylemek için uygulamam gerekiyorsa, sadece çalıştırıyorum.

find . -name '*.[CHch]' -print0 | xargs -r0 ~/bin/ms-fix

veya, sadece böyle bir dosyaya bakmak istersem, değiştirmeden çalıştırabilirim

~/bin/ms-fix < filename | less

ve <U+FEFF>UTF-8 terminalimde çirkin görmüyorum .


Neden basitçe değil sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- "$@"?
Stéphane Chazelas

@ StéphaneChazelas: Yapılması gereken bir sorun varsa betiğin hemen çıkmasını istiyorum sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- "$@"; bir çıkış kodu döndürür, ancak çıkmadan önce argüman listesinde listelenen tüm dosyaları işler.
Nominal Hayvan

@ StéphaneChazelas: --Elbette, dosya adlarından önce, elbette, önemli: onsuz, kısa bir çizgi ile başlayan dosya adları sed. Bunları cevabımı düzenledim; hatırlatma için teşekkür ederim!
Nominal Hayvan

0

Son zamanlarda, UTF-8 kodlanmış dosyalarına BOM ekleyen veya silen bu küçük komut satırı aracını buldum: UTF BOM Utils ( github'daki yeni bağlantı )

Küçük dezavantajı, sadece düz C ++ kaynak kodunu indirebilirsiniz. Makefile dosyasını oluşturmalısınız ( örneğin, CMake ile ) ve kendiniz derleyin, bu sayfada ikili dosyalar bulunmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.