Tôi có một tệp ở dạng mã hóa UTF-8 với BOM và muốn xóa BOM. Có công cụ dòng lệnh linux nào để loại bỏ BOM khỏi tệp không?
$ file test.xml
test.xml: XML 1.0 document, UTF-8 Unicode (with BOM) text, with very long lines
Tôi có một tệp ở dạng mã hóa UTF-8 với BOM và muốn xóa BOM. Có công cụ dòng lệnh linux nào để loại bỏ BOM khỏi tệp không?
$ file test.xml
test.xml: XML 1.0 document, UTF-8 Unicode (with BOM) text, with very long lines
Câu trả lời:
Nếu bạn không chắc liệu tệp có chứa BOM UTF-8 hay không, thì điều này (giả sử việc triển khai GNU sed
) sẽ xóa BOM nếu nó tồn tại hoặc không thay đổi nếu không.
sed '1s/^\xEF\xBB\xBF//' < orig.txt > new.txt
Bạn cũng có thể ghi đè lên tệp hiện có với -i
tùy chọn:
sed -i '1s/^\xEF\xBB\xBF//' orig.txt
en_US.UTF-8
miền địa phương và nó đã hoạt động. Khi nào nó sẽ thất bại?
1s/
có nghĩa là chỉ tìm kiếm dòng đầu tiên; các dòng khác không bị ảnh hưởng. Các ^
phương tiện chỉ phù hợp ở đầu dòng (đầu tiên). \xEF\xBB\xBF
là BOM UTF-8 (chuỗi hex đã thoát). //
có nghĩa là thay thế bằng không có gì. Tôi có thể đã thêm vào 1
cuối (cho 1s/^xEF\xBB\xBF//1
), điều đó có nghĩa là chỉ phù hợp với lần xuất hiện đầu tiên của mẫu trên dòng. Nhưng khi tìm kiếm được gắn kết ^
, điều này sẽ không tạo ra bất kỳ sự khác biệt nào. Nếu tệp không có BOM ở đầu dòng đầu tiên, mẫu sẽ không khớp và do đó không có thay đổi nào được thực hiện.
Một BOM không có ý nghĩa trong UTF-8. Chúng thường được thêm vào do nhầm lẫn bởi phần mềm không có thật trên hệ điều hành Microsoft.
dos2unix
sẽ loại bỏ nó và cũng sẽ xử lý các đặc điểm riêng khác của các tệp văn bản Windows.
dos2unix test.xml
dos2unix
?
Có thể xóa BOM khỏi một tệp bằng tail
lệnh:
tail -c +4 withBOM.txt > withoutBOM.txt
tail
đang sử dụng lập chỉ mục 1?! WTF!
tail -c -1
hoặc tail -c 1
( tail
thường được sử dụng cho) là nội dung bắt đầu bằng byte cuối cùng, tail -c +1
bắt đầu bằng byte đầu tiên. tail -c 0
/ tail -c +0
cho điều đó sẽ không trực quan hơn nhiều.
(dd bs=1 count=3 of=/dev/null; cat) <input >output
. Hoặc với GNU (head -c3 >/dev/null; cat)
- ngay cả trong UTF8 hoặc ngôn ngữ không đơn lẻ khác; Đầu GNU không 'char' = byte.
Mở tệp trong VIM:
vi text.xml
Xóa mã hóa BOM:
:set nobomb
Lưu và thoát:
:wq
<feff>
, nhưng :set nobomb
không sửa đổi hoặc xóa nó.
Bạn có thể dùng
LANG=C LC_ALL=C sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- filename
để loại bỏ dấu thứ tự byte khỏi phần đầu của tệp, nếu nó có bất kỳ, cũng như chuyển đổi bất kỳ dòng mới CR LF nào thành LF. Nó báo LANG=C LC_ALL=C
cho shell mà bạn muốn lệnh chạy trong miền địa phương C mặc định (còn được gọi là miền địa phương POSIX mặc định), trong đó ba byte tạo thành Dấu thứ tự Byte được coi là byte. Các -i
tùy chọn để sed nghĩa tại chỗ. Nếu bạn sử dụng -i.old
, thì sed sẽ lưu tệp gốc dưới dạng filename.old
và tệp mới (với các sửa đổi, nếu có) như filename
.
Cá nhân tôi thích có cái này như ~/bin/fix-ms
; ví dụ như
#!/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
để nếu tôi cần áp dụng điều này để nói tất cả các tệp và tiêu đề nguồn C (ví dụ mã cũ của tôi từ thời MS-DOS!), tôi chỉ cần chạy
find . -name '*.[CHch]' -print0 | xargs -r0 ~/bin/ms-fix
hoặc, nếu tôi chỉ muốn xem một tệp như vậy, mà không sửa đổi nó, tôi có thể chạy
~/bin/ms-fix < filename | less
và không thấy xấu xí <U+FEFF>
trong thiết bị đầu cuối UTF-8 của tôi.
sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- "$@"
?
sed -e 's/\r$// ; 1 s/^\xef\xbb\xbf//' -i -- "$@"
này không xảy ra; nó trả về một mã thoát, nhưng nó xử lý tất cả các tệp được liệt kê trong danh sách đối số trước khi thoát.
--
trước khi tên tệp là quan trọng: không có nó, tên tệp bắt đầu bằng dấu gạch ngang có thể được coi là tùy chọn của sed. Tôi chỉnh sửa chúng thành câu trả lời của tôi; cảm ơn bạn đã nhắc nhở!
Gần đây tôi đã tìm thấy công cụ dòng lệnh nhỏ này có thêm hoặc xóa BOM trên các tệp được mã hóa UTF-8 tùy ý: UTF BOM Utils ( liên kết mới tại github)
Hạn chế nhỏ, bạn chỉ có thể tải xuống mã nguồn C ++ đơn giản. Bạn phải tạo tệp tạo tệp ( ví dụ với CMake ) và tự biên dịch nó, các tệp nhị phân không được cung cấp trên trang này.