Вопрос по linux, unicode, bash – Как я могу повторно добавить маркер порядка байтов Юникода в Linux?

12

У меня довольно большой файл SQL, который начинается с маркера порядка байтов FFFE. Я разбил этот файл с помощью инструмента разбивки linux с поддержкой Unicode на 100 000 строк. Но при передаче их обратно в окна, это делаетnot как любая из частей, кроме первой, только на ней есть маркер порядка следования байтов FFFE.

Как я могу добавить этот двухбайтовый код, используя echo (или любую другую команду bash)?

Ваш Ответ

7   ответов
1
$ printf '\xEF\xBB\xBF' > bom.txt

Затем проверьте:

$ grep -rl $'\xEF\xBB\xBF' .
./bom.txt
4

for i in $(ls *.sql)
do
  cp "$i" "$i.temp"
  printf '\xFF\xFE' > "$i"
  cat "$i.temp" >> "$i"
  rm "$i.temp"
done
Кодовая точка спецификации - U + FEFF, но ее буквальное представление в UTF-8EF BB BF (три байта). Это будет работать только в том случае, если файл уже был в UTF-16, порядок в порядке байтов. Увидетьen.wikipedia.org/wiki/…
Printf! Спасибо, приятель, я думаю, что я гуглил до конца времени! Neil Trodden
3

Попробуй uconv

uconv --add-signature
Нужно установить uconv (в Debian он находится в пакете libicu-dev). Не то, что add-signature не работает, если файл находится в другой кодировке.
2

There's no check that the copy succeeded before the original file is truncated. It would be better to make everything contingent on a successful copy, or test for the existence of the temporary file, or to operate on the copy. If you're a belt-and-suspenders kind of person, you'd do a combo as I've illustrated below The ls is unnecessary. I'd use a better variable name than "i" - perhaps "file".

Конечно, вы могли бы бытьvery Параноик и проверьте наличие временного файла в начале, чтобы вы случайно не перезаписали его и / или не использовали UUID или сгенерированное имя файла. Один из mktemp, tempfile или uuidgen сделает свое дело.

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

Ловушки могут быть лучше, чем все отдельные обработчики ошибок, которые я добавил.

Без сомнения, все эти дополнительные предосторожности являются излишними для сценария с одним выстрелом, но эти методы могут спасти вас, когда наступает время пуша, особенно в многофайловой операции.

& Quot; cp & quot; Команда не нужна. Также "mktemp" возвращает имя в / tmp; было бы лучше написать временный файл в той же файловой системе, чтобы & quot; mv & quot; не нужно будет копировать его.
@ mark4o: Вы правы в обоих случаях. Я обновил свой ответ соответственно.
15

решение Anonymous, sed -i '1s/^/\xef\xbb\xbf/' foo добавляет спецификацию в кодированный файл UTF-8foo, Полезно то, что он также конвертирует файлы ASCII в UTF8 с спецификацией

11

foo- & quot ;, вы можете использоватьsed. sed имеет возможность сделать резервную копию.

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

straceВ этом примере sed создает временный файл с именем, начинающимся с & quot; sed & quot ;. Если вы точно знаете, что спецификации уже нет, вы можете упростить команду:

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

Убедитесь, что вам нужно установить UTF-16, потому что то есть UTF-8 отличается.

Кстати,g (глобальный) модификатор здесь ничего не делает.
@AnthonyGeoghegan Ой, спасибо.
Голосую за этот ответ, потому что это то, чем я пользуюсь сам. Mac OS и другие пользователи BSD должны знать, что-i,--inplace опция не указана в POSIX и доступна только с GNU sed.
Для использования в UTF-8\xef\xbb\xbf; для UTF-16 с прямым порядком байтов\xff\xfe; для UTF-16 с прямым порядком байтов\xfe\xff, Увидетьw3.org/International/questions/qa-byte-order-mark
9

которое устанавливает правильную метку порядка байтов, независимо от того, является ли файл UTF-8, UTF-16 или UTF-32 & # x2014; я бы использовал vim & # x2019; s'bomb' опция:

$ 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 значит работает в режиме ex вместо визуального режима;-s означает не печатать сообщения о состоянии;-c означает & # x201C; сделать это & # x201D;)

Похожие вопросы