Bayt sırası işaretini kaldırmak için awk kullanma


105

awkBir malzeme listesini kaldırmak için bir komut dosyası (muhtemelen tek satırlık) nasıl görünür?

Şartname:

  • ilk satırdan sonra her satırı yazdır ( NR > 1)
  • ilk satır için: #FE #FFveya ile başlıyorsa #FF #FE, bunları kaldırın ve kalanını yazdırın

Yanıtlar:


114

Bunu dene:

awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}{print}' INFILE > OUTFILE

İlk kayıtta (satır), BOM karakterlerini kaldırın. Her kaydı yazdırın.

Veya biraz daha kısa, awk'deki varsayılan eylemin kaydı yazdırmak olduğu bilgisini kullanarak:

awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1' INFILE > OUTFILE

1 her zaman doğru olarak değerlendirilen en kısa koşuldur, bu nedenle her kayıt yazdırılır.

Zevk almak!

- EK -

Unicode Bayt Sırası İşareti (BOM) SSS , her kodlama için tam ürün reçetesi baytlarını listeleyen aşağıdaki tabloyu içerir:

Bytes         |  Encoding Form
--------------------------------------
00 00 FE FF   |  UTF-32, big-endian
FF FE 00 00   |  UTF-32, little-endian
FE FF         |  UTF-16, big-endian
FF FE         |  UTF-16, little-endian
EF BB BF      |  UTF-8

Böylece, yukarıdaki tablodan BOM baytlarına nasıl \xef\xbb\xbfkarşılık geldiğini görebilirsiniz EF BB BF UTF-8.


1
Görünüşe göre alt ifadenin ortasındaki nokta çok fazla (en azından benim awk'm bundan şikayet ediyor). Bunun yanında tam olarak aradığım şey bu, teşekkürler!
Boldewyn 01

5
Ancak bu çözüm yalnızca UTF-8 kodlu dosyalar için çalışır . UTF-16 gibi diğerleri için, ilgili ürün reçetesi temsili için Wikipedia'ya bakın: en.wikipedia.org/wiki/Byte_order_mark
Boldewyn

2
Öyleyse: awk '{if(NR==1)sub(/^\xef\xbb\xbf/,"");print}' INFILE > OUTFILEINFILE ve OUTFILE'ın farklı olduğundan emin olun!
Steve Clay

1
Eğer kullandıysanız perl -i.orig -pe 's/^\x{FFFE}//' badfileEğer şifreleme için PERL_UNICODE ve / veya PERLIO envariables güvenebileceğini. PERL_UNICODE = SD, UTF-8 için çalışacaktır; diğerleri için PERLIO'ya ihtiyacınız var.
tchrist

1
Belki biraz daha kısa versiyon:awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1'
TrueY

122

GNU kullanarak sed(Linux veya Cygwin'de):

# Removing BOM from all text files in current directory:
sed -i '1 s/^\xef\xbb\xbf//' *.txt

FreeBSD'de:

sed -i .bak '1 s/^\xef\xbb\xbf//' *.txt

GNU veya FreeBSD kullanmanın avantajı sed: -iparametre "yerinde" anlamına gelir ve yeniden yönlendirmelere veya garip numaralara gerek kalmadan dosyaları günceller.

Mac'te:

Bu awkçözüm başka bir cevapta işe yarıyor , ancak sedyukarıdaki komut çalışmıyor. En azından Mac (Sierra) seddokümantasyonunda onaltılık kaçmayı desteklediğinden bahsetmiyor \xef.

Benzer bir numara, herhangi bir programda moreutils'tensponge araca bağlanarak elde edilebilir :

awk '…' INFILE | sponge INFILE

5
İkinci komutu tam olarak Mac OS X üzerinde denedim ve sonuç "başarılı" oldu, ancak ikame gerçekleşmedi.
Trejkaz

1
Bu komutların , olası bayt sırası işaretlerinden biri olan belirli bir bayt dizisinin yerini aldığını belirtmek gerekir . Belki dosyanızın farklı bir ürün reçetesi dizisi vardır. (Bir Mac'im olmadığı için bundan başka yardım edemem)
Denilson Sá Maia

3
OS X üzerindeki ikinci komutu, BOM olarak 0xef 0xbb 0xbf kullanan bir dosyada denediğimde, aslında ikame yapmadı.
John Wiseman

OSX'te, burada gösterildiği gibi bunu yalnızca perl aracılığıyla çalıştırabildim: stackoverflow.com/a/9101056/2063546
Ian

OS X El Capitan'da 10.11.6bu işe yaramıyor, ancak resmi yanıt stackoverflow.com/a/1068700/9636 iyi çalışıyor.
Heath Borders

42

Awk değil, daha basit:

tail -c +4 UTF8 > UTF8.nobom

Malzeme Listesini kontrol etmek için:

hd -n 3 UTF8

Ürün reçetesi varsa şunları göreceksiniz: 00000000 ef bb bf ...


6
BOM'lar UTF-16 için 2 bayt ve UTF-32 için 4 bayttır ve elbette ilk etapta UTF-8'de iş yoktur.
tchrist

2
@KarolyHorvath Evet, kesinlikle. Kullanımı tavsiye edilmez. Bir şeyleri kırar. Kodlama, daha yüksek seviyeli bir protokol tarafından belirtilmelidir.
tchrist

1
@tchrist: Kırık şeyleri kırdığını mı söylüyorsun? :) uygun uygulamalar bu ürün reçetesini işleyebilmelidir.
Karoly Horvath

7
@KarolyHorvath Demek istediğim birçok programı bozuyor . Ben de öyle değil mi? UTF-16 veya UTF-32 kodlamalarında bir akışı açtığınızda, kod çözücü BOM'u saymayacağını bilir. UTF-8 kullandığınızda, kod çözücüler ürün reçetesini veri olarak sunar. Bu, sayısız programdaki bir sözdizimi hatasıdır. Java'nın kod çözücüsü bile bu şekilde davranır, TASARIMLA! UTF-8 dosyalarındaki BOM'lar yanlış yerleştirilmiş ve baş belası: bunlar bir hatadır! Birçok şeyi kırarlar. Sadece bile cat file1.utf8 file2.utf8 file3.utf3 > allfiles.utf8kırılacak. UTF-8'de asla bir BOM kullanmayın. Dönem.
tchrist

6
hd(10.8.2 itibariyle) OS X üzerinde mevcut değildir, bu nedenle kontrol etmek için UTF-8 BOM orada aşağıdakileri kullanabilirsiniz: head -c 3 file | od -t x1.
mklement 0

21

CRLF satır sonlarını LF'ye dönüştürmenin yanı sıra, dos2unixBOM'leri de kaldırır:

dos2unix *.txt

dos2unix ayrıca BOM içeren UTF-16 dosyalarını (ancak BOM içermeyen UTF-16 dosyalarını değil), BOM olmadan UTF-8'e dönüştürür:

$ printf '\ufeffä\n'|iconv -f utf-8 -t utf-16be>bom-utf16be
$ printf '\ufeffä\n'|iconv -f utf-8 -t utf-16le>bom-utf16le
$ printf '\ufeffä\n'>bom-utf8
$ printf 'ä\n'|iconv -f utf-8 -t utf-16be>utf16be
$ printf 'ä\n'|iconv -f utf-8 -t utf-16le>utf16le
$ printf 'ä\n'>utf8
$ for f in *;do printf '%11s %s\n' $f $(xxd -p $f);done
bom-utf16be feff00e4000a
bom-utf16le fffee4000a00
   bom-utf8 efbbbfc3a40a
    utf16be 00e4000a
    utf16le e4000a00
       utf8 c3a40a
$ dos2unix -q *
$ for f in *;do printf '%11s %s\n' $f $(xxd -p $f);done
bom-utf16be c3a40a
bom-utf16le c3a40a
   bom-utf8 c3a40a
    utf16be 00e4000a
    utf16le e4000a00
       utf8 c3a40a

3

Sorunun unix / linux'a yönelik olduğunu biliyorum, unix'e meydan okuyanlar için iyi bir seçenekten bahsetmeye değer olduğunu düşündüm (pencerelerde, bir UI ile).
Bir WordPress projesinde aynı sorunla karşılaştım (BOM, rss beslemesi ve sayfa doğrulamasında sorunlara neden oluyordu) ve BOM ile olanı bulmak için oldukça büyük bir dizin ağacındaki tüm dosyalara bakmam gerekti. Replace Pioneer adlı bir uygulama buldum ve içinde:

Toplu Çalıştırıcı -> Ara (alt klasörlerdeki tüm dosyaları bulmak için) -> Şablonu Değiştir -> İkili, BOM'yi kaldır (bunun için hazır bir arama ve değiştirme şablonu vardır).

En zarif çözüm değildi ve bir dezavantajı olan bir program yüklemeyi gerektiriyordu. Ama etrafımda neler döndüğünü öğrendiğimde, bir cazibe gibi çalıştı (ve BOM ile olan yaklaşık 2300 dosyadan 3'ünü buldu).


1
Çözümünüzü bulduğumda çok mutluyum ancak şirket bilgisayarına yazılım yükleme ayrıcalığına sahip değilim. Bugün alternatifini bulana kadar çok zaman aldı: PythonScript eklentisi ile Notepad ++ kullanmak. superuser.com/questions/418515/… Yine de teşekkürler!
Hoàng Long
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.