Возникли проблемы с пакетным скриптом

#file #unicode #batch-file

#файл #Юникод #пакетный файл

Вопрос:

У меня есть пакетный скрипт, который выполняет вызов с помощью sqlcmd для извлечения результатов инструкции SELECT в файл с именем temp.txt . В данных присутствуют некоторые посторонние символы, которые требуют от нас использования Unicode, поэтому temp.txt используется Unicode (кодовая страница 65001).

Как только данные в temp.txt скрипт подсчитывает количество строк и добавляет некоторые заголовки. Чтобы сделать это, он должен создать новый файл (назовем его newfile.txt ), добавьте заголовки и количество строк, а затем скопируйте в каждую строку из temp.txt для newfile.txt .

Все это работает нормально, за исключением того, что первая строка скопирована из temp.txt содержит знак порядка байтов в Юникоде; это означает, что первая строка, вместо того, чтобы выглядеть так:

 1, Custom Page
  

вместо этого выглядит так:

 1, Custom Page
  

Я не могу понять, как наилучшим образом справиться с этим.

Если бы я мог сказать sqlcmd предоставить мне Unicode без спецификации, это было бы идеально — попробовал поискать в Google, не смог понять.

Если бы я мог понять, как написать пакетный файл для цикла, который удаляет первые три символа только первой строки при копировании в temp.txt Я бы попробовал это, но после некоторого поиска в Google и экспериментов я разочарован.

Для записи соответствующий код выглядит следующим образом:

 ::%1 = sql file to call; %2 = filename to be created; %3 = header for file; %4 = data type row for file
sqlcmd -I -f 65001 -W -k 1 -h -1 -s "," -S servername -d dbname -i %1 -o temp.txt
set counter=0
for /f %%a in (temp.txt) do set /a counter =1
echo ^^!total rows=%counter% >> %2
echo !str1! >> %2
echo !str2! >> %2
for /F "delims=¶" %%i in (temp.txt) do ( echo %%i >> %2 )
  

Пожалуйста, помогите мне, я схожу с ума из-за этой нелепой маленькой проблемы.

Ответ №1:

Вы могли бы попробовать

 chcp 65001
  

в вашем пакетном скрипте перед вызовом sqlcmd. Это было бы не совсем интуитивно, но, возможно, это играет роль.

Если все остальное не удается, создайте собственную версию bomstrip , и вы должны быть в курсе.

HTH

Обновить

У меня есть «исправленная» версия для Windows, которая повторно откроет stdin / stdout в двоичном режиме, так что вы избежите автоматического преобразования концов строк (sic!):

 #include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

void
usage(char *prog)
{
    fprintf(stderr, "usage: %sn", prog);
    exit(1);
}

int
main(int argc, char *argv[])
{
    size_t nread;
    char buf[65536];
    char *utf8bom = "xefxbbxbf";

    if (argc > 1)
        usage(argv[0]);

    /*
     * On Windows, we need to use binary mode to read/write non-text archive
     * formats.  Force stdin/stdout into binary mode in case that is what
     * we are using.
     */
#ifdef WIN32
    if (fmt != archNull)
    {
        setmode(fileno(stdout), O_BINARY);
        setmode(fileno(stdin), O_BINARY);
    }
#endif
    nread = fread(buf, 1, strlen(utf8bom), stdin);
    if (nread == 0)
        return 0;
    if (strcmp(buf, utf8bom) != 0)
        fwrite(buf, 1, nread, stdout);
    for (;;) {
        nread = fread(buf, 1, sizeof buf, stdin);
        if (nread < 0)
            exit(1);
        if (nread == 0)
            return 0;
        fwrite(buf, 1, nread, stdout);
    }
    return 0;
}
  

Теперь вы можете сделать:

 > .bomstrip.exe < withoutbom > test
> md5sum.exe withoutbom test
f9f2e33bb16636f990180fa3fcbc93cb *withoutbom
f9f2e33bb16636f990180fa3fcbc93cb *test
  

Комментарии:

1. О да, я использую chcp 65001 перед вставкой кода. Я попробую bomstrip, хотя не похоже, что его можно вызвать из командной строки.

2. Я скомпилировал один на случай, если вы застряли. Мне просто нужно было бы отправить его, чтобы разместить где-нибудь на веб-сайте

3. Я его скомпилировал, просто пытаюсь выяснить, как вызвать его из командной строки.

4. bomstrip < input.txt > output.txt это фильтр в стиле UNIX.

5. Я только что узнал, что bomstrip по умолчанию будет преобразовывать строки, если вы использовали версию C, я включил исправленную версию этого в свой пост здесь