2009-06-25 22 views
10

Tôi có một tệp SQL khá lớn bắt đầu với điểm đánh dấu thứ tự byte của FFFE. Tôi đã chia nhỏ tập tin này bằng cách sử dụng công cụ phân chia Linux unicode nhận biết thành 100.000 khối dòng. Nhưng khi chuyển các cửa sổ này trở lại, nó không phải giống như bất kỳ phần nào khác ngoài phần đầu tiên vì chỉ có điểm đánh dấu thứ tự byte FFFE.Làm cách nào để tôi có thể thêm lại một điểm đánh dấu thứ tự byte unicode trong linux?

Làm cách nào để thêm mã hai byte này bằng cách sử dụng echo (hoặc bất kỳ lệnh bash nào khác)?

Trả lời

4

Giống như (sao lưu đầu tiên)): Câu trả lời

for i in $(ls *.sql) 
do 
    cp "$i" "$i.temp" 
    printf '\xFF\xFE' > "$i" 
    cat "$i.temp" >> "$i" 
    rm "$i.temp" 
done 
+0

printf! Cảm ơn bạn đời, tôi nghĩ rằng tôi đã googling cho đến khi kết thúc thời gian! –

+6

Điểm mã BOM là U + FEFF nhưng biểu diễn bằng chữ của nó trong UTF-8 là 'EF BB BF' (ba byte). Điều này sẽ chỉ hoạt động nếu tập tin đã có trong UTF-16, thứ tự nhỏ. Xem http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding – pimlottc

2

Matthew Flaschen là một tốt nhất, tuy nhiên nó có một vài sai sót.

  • Không kiểm tra xem bản sao đã thành công trước khi tệp gốc bị cắt bớt hay chưa. Sẽ tốt hơn nếu làm cho mọi thứ phụ thuộc vào bản sao thành công hoặc kiểm tra sự tồn tại của tệp tạm thời hoặc để hoạt động trên bản sao. Nếu bạn là một loại người treo đai và treo, bạn sẽ thực hiện một kết hợp như tôi đã minh họa bên dưới
  • ls là không cần thiết.
  • Tôi muốn sử dụng tên biến tốt hơn "i" - có lẽ là "tệp".

Tất nhiên, bạn có thể rất hoang tưởng và kiểm tra sự tồn tại của tập tin tạm thời ngay từ đầu, do đó bạn không vô tình ghi đè lên nó và/hoặc sử dụng một UUID hoặc một tên tập tin được tạo ra. Một trong những mktemp, tempfile hoặc uuidgen sẽ làm điều này.

td=TMPDIR 
export TMPDIR= 

usertemp=~/temp   # set this to use a temp directory on the same filesystem 
          # you could use ./temp to ensure that it's one the same one 
          # you can use mktemp -d to create the dir instead of mkdir 

if [[ ! -d $usertemp ]] # if this user temp directory doesn't exist 
then      # then create it, unless you can't 
    mkdir $usertemp || export TMPDIR=$td # if you can't create it and TMPDIR is/was 
fi           # empty then mktemp automatically falls 
              # back to /tmp 

for file in *.sql 
do 
    # TMPDIR if set overrides the argument to -p 
    temp=$(mktemp -p $usertemp) || { echo "$0: Unable to create temp file."; exit 1; } 

    { printf '\xFF\xFE' > "$temp" && 
    cat "$file" >> "$temp"; } || { echo "$0: Write failed on $file"; exit 1; } 

    { rm "$file" && 
    mv "$temp" "$file"; } || { echo "$0: Replacement failed for $file; exit 1; } 
done 
export TMPDIR=$td 

Bẫy có thể tốt hơn tất cả các trình xử lý lỗi riêng biệt mà tôi đã thêm. Không có nghi ngờ gì về sự thận trọng này là quá mức cần thiết cho một kịch bản một lần, nhưng những kỹ thuật này có thể giúp bạn tiết kiệm khi đẩy xô đẩy, đặc biệt là trong một thao tác đa tệp.

+1

Lệnh "cp" không cần thiết. Ngoài ra "mktemp" trả về một tên trong/tmp; nó sẽ là tốt hơn để viết các tập tin tạm thời trên cùng một hệ thống tập tin để "mv" sẽ không phải sao chép nó. – mark4o

+0

@ mark4o: Bạn đúng trên cả hai số. Tôi đã cập nhật câu trả lời của mình cho phù hợp. –

9

Đối với một mục đích chung giải pháp cái gì đó đặt dấu byte-theo đúng thứ tự bất kể file là UTF-8, UTF-16, hay UTF-32-I sẽ sử dụng 'bomb' tùy chọn vim của:

$ echo 'hello' > foo 
$ xxd < foo 
0000000: 6865 6c6c 6f0a       hello. 
$ vim -e -s -c ':set bomb' -c ':wq' foo 
$ xxd < foo 
0000000: efbb bf68 656c 6c6f 0a     ...hello. 

(-e nghĩa chạy trong chế độ cũ thay vì chế độ trực quan; -s phương tiện không in thông điệp trạng thái; -c có nghĩa là “làm được điều này”)

10

để thêm BOMs đến tất cả các file bắt đầu bằng "foo-" , bạn có thể sử dụng sed. sed có tùy chọn sao lưu.

sed -i '1s/^\(\xff\xfe\)\?/\xff\xfe/' foo-* 

strace ing này cho thấy sed tạo tệp tạm thời có tên bắt đầu bằng "sed". Nếu bạn biết chắc chắn không có BOM, bạn có thể đơn giản hóa lệnh:

sed -i '1s/^/\xff\xfe/' foo-* 

Đảm bảo bạn cần đặt UTF-16, vì UTF-8 khác.

+1

Đối với UTF-8, sử dụng '\ xef \ xbb \ xbf'; để sử dụng UTF-16 nhỏ gọn '\ xff \ xfe'; để sử dụng UTF-16 lớn nhất '\ xfe \ xff'. Xem https://www.w3.org/International/questions/qa-byte-order-mark –

+0

Upvoting câu trả lời này bởi vì đây là những gì tôi sử dụng bản thân mình. Mac OS và những người dùng BSD khác nên cẩn thận rằng tùy chọn '-i, - inplace' không được chỉ định bởi POSIX và chỉ có sẵn với GNU sed. –

+1

BTW, công cụ sửa đổi 'g' (toàn cầu) không làm bất cứ điều gì ở đây. –

3

Hãy thử uconv

uconv --add-signature 
+1

uconv cần được cài đặt (trong Debian, nó nằm trong gói libicu-dev). Không phải là chữ ký bổ sung đó không hoạt động nếu tệp ở dạng mã hóa khác. – Rob

13

Dựa trên sed của solution of Anonymous, sed -i '1s/^/\xef\xbb\xbf/' foo thêm BOM để UTF-8 mã hóa tập tin foo. Hữu ích là nó cũng chuyển đổi các file ASCII để UTF8 với BOM

0
$ printf '\xEF\xBB\xBF' > bom.txt 

Sau đó kiểm tra:

$ grep -rl $'\xEF\xBB\xBF' . 
./bom.txt 
Các vấn đề liên quan