awkを使用してバイト順マークを削除する


105

どうでしょうawk取り除くためのスクリプト(おそらくワンライナー)BOMのような外観を?

仕様:

  • 最初の(NR > 1)の後にすべての行を出力する
  • 1行目:#FE #FFまたはで始まる場合#FF #FEは削除して、残りを印刷します

回答:


114

これを試して:

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

最初のレコード(行)で、BOM文字を削除します。すべてのレコードを印刷します。

または、少し短く、awkのデフォルトのアクションはレコードを印刷することであるという知識を使用します。

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

1 常にtrueと評価される最短の条件なので、各レコードが出力されます。

楽しい!

-補遺-

Unicodeバイトオーダーマーク(BOM)のFAQには、各エンコーディングの正確なBOMバイトをリストした次の表が含まれています。

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

したがって、上の表からBOMバイトにどのように\xef\xbb\xbf対応するかがわかりEF BB BF UTF-8ます。


1
サブステートメントの中央にあるドットが多すぎるようです(少なくとも、私のawkはそれについて不平を言っています)。これのほかに、それはまさに私が検索したものです、ありがとう!
Boldewyn、2009

5
ただし、このソリューションはUTF-8でエンコードされたファイルに対してのみ機能します。UTF-16のような他のものについては、対応するBOM表現についてWikipediaを参照してください:en.wikipedia.org/wiki/Byte_order_mark
Boldewyn

2
だから:awk '{if(NR==1)sub(/^\xef\xbb\xbf/,"");print}' INFILE > OUTFILEそしてINFILEとOUTFILEが異なることを確認してください!
Steve Clay、

1
使用したperl -i.orig -pe 's/^\x{FFFE}//' badfile場合は、エンコーディングにPERL_UNICODEやPERLIO変数を使用できます。PERL_UNICODE = SDはUTF-8で機能します。他の人にはPERLIOが必要です。
tchrist

1
多分少し短いバージョン:awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1'
TrueY

122

GNU sed(LinuxまたはCygwin)の使用:

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

FreeBSDの場合:

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

GNUまたはFreeBSDを使用する利点sed:この-iパラメーターは「インプレース」を意味し、リダイレクトや奇妙なトリックを必要とせずにファイルを更新します。

Macの場合:

awk別の答えでこの解決策は機能しますが、sed上記のコマンドは機能しません。少なくともMac(Sierra)のsedドキュメントでは、16進エスケープalaのサポートについて言及されていません\xef

moreutilsspongeからツールにパイプすることで、どのようなプログラムでも同様のトリックを実現できます。

awk '…' INFILE | sponge INFILE

5
Mac OS Xで2番目のコマンドを正確に試しましたが、結果は「成功」でしたが、実際には置換は行われませんでした。
Trejkaz

1
これらのコマンドが特定のバイトシーケンスを置き換えることに注意してください。これは、可能なバイトオーダーマークの1つです。多分あなたのファイルは異なるBOMシーケンスを持っていました。(Macを持っていないので、それ以外は何もできません)
DenilsonSáMaia

3
BOMとして0xef 0xbb 0xbfを使用するファイルでOS Xの2番目のコマンドを試したところ、実際には置換されませんでした。
John Wiseman

OSXでは、以下に示すように、これをperl経由でのみ機能させることができます。stackoverflow.com
Ian

OS X El Capitan 10.11.6では、これは機能しませんが、公式の回答であるstackoverflow.com/a/1068700/9636は正常に機能します。
ヒースボーダー

42

awkではありませんが、より単純です:

tail -c +4 UTF8 > UTF8.nobom

BOMを確認するには:

hd -n 3 UTF8

BOMが存在する場合は、次のように表示されます。 00000000 ef bb bf ...


6
BOMは、UTF-16の場合は2バイト、UTF-32の場合は4バイトです。もちろん、そもそもUTF-8を使用しているビジネスはありません。
tchrist

2
@KarolyHorvathはい、正確に。その使用は推奨されません。それはものを壊します。エンコーディングは、より上位のプロトコルで指定する必要があります。
tchrist

1
@tchrist:壊れたものを壊すということですか?:)適切なアプリがそのBOMを処理できる必要があります。
Karoly Horvath

7
@KarolyHorvath私はそれが多くのプログラムを壊すことを意味します。私の言ったことじゃないですか?UTF-16またはUTF-32エンコーディングでストリームを開くと、デコーダはBOMをカウントしないことを認識します。UTF-8を使用すると、デコーダーはBOMをデータとして表示します。これは無数のプログラムの構文エラーです。Javaのデコーダでさえ、このように動作します。UTF-8ファイルのBOMは置き間違えられ、お尻の痛み:エラーです!彼らは多くのものを壊します。cat file1.utf8 file2.utf8 file3.utf3 > allfiles.utf8壊れるだけです。UTF-8でBOMを使用しないでください。限目。
tchrist

6
hdOS X(10.8.2以降)では使用できません。そのため、UTF-8 BOMを確認するには、以下を使用できますhead -c 3 file | od -t x1
mklement0

21

CRLF行末をLFに変換するだけでなく、dos2unixBOMも削除します。

dos2unix *.txt

dos2unix また、BOMのあるUTF-16ファイル(ただしBOMのないUTF-16ファイルは不可)をBOMのないUTF-8に変換します。

$ 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

私は質問がunix / linuxに向けられていたことを知っていて、unixに挑戦する(Windowsで、UIを使用する)ための良いオプションについて言及する価値があると思いました。
WordPressプロジェクトで同じ問題に遭遇し(BOMがrssフィードとページ検証で問題を引き起こしていた)、BOMにあるファイルを見つけるために非常に大きなディレクトリツリーのすべてのファイルを調べる必要がありました。Replace Pioneerというアプリケーションを見つけ、その中に:

バッチランナー->検索(サブフォルダー内のすべてのファイルを検索)->テンプレートの置換->バイナリーBOMの削除(このための既製の検索および置換テンプレートがあります)。

これは最もエレガントなソリューションではなく、プログラムをインストールする必要がありましたが、これは欠点です。しかし、周りに何が起こっているのかがわかると、それは魅力のように機能しました(BOMに関連する約2300のうち3つのファイルが見つかりました)。


1
あなたの解決策を見つけたときはとても幸せですが、会社のコンピュータにソフトウェアをインストールする特権がありません。代替案を見つけるまで、今日は多くの時間を要しました。PythonScriptプラグインでNotepad ++を使用することです。 superuser.com/questions/418515/…とにかくありがとう!
ホアンロング
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.