Пакетный скрипт Windows для копирования и изменения файлов, содержащих символы перенаправления - PullRequest
0 голосов
/ 21 августа 2009

Мы пытаемся преобразовать скрипт оболочки bash в пакетный скрипт Windows. Мы поставляем эти скрипты вместе с нашим программным продуктом, и мы не можем предполагать, что у клиента будет или будет возможность загрузить sed / awk / cygwin или любые другие нестандартные инструменты. Таким образом, сценарий должен работать с любыми инструментами, входящими в комплект поставки Windows. Минимальная целевая платформа - Windows XP SP2. Этот скрипт вызывается из другого пакетного скрипта.

Одна часть скрипта должна найти в файле определенную строку и изменить ее. В bash это легко. Подход, который мы используем в пакетном скрипте Windows, заключается в том, чтобы построчно просматривать файл. Если строка не содержит целевой строки, мы выводим ее во временный файл как есть. Если строка содержит целевую строку, мы выводим жестко закодированную строку во временный файл.

Проблема в том, что некоторые строки входного файла содержат знаки «меньше» и «больше». Если мы поместим кавычки вокруг строк, они будут записаны без изменений во временный файл, но заключены в кавычки.

"-- this is a comment in the output .sql file"
"SELECT foo FROM bar WHERE something < 10;"
"--<SpecialInternalTagComment>"

Если мы заключим их в кавычки, используя% ~ 1, то CMD.EXE попытается обработать символы <и> как символы перенаправления и выдает ошибки, когда скрипт встречает одну из этих строк, потому что получающаяся команда будет выглядеть примерно так: 1008 *

echo --<SpecialInternalTagComment> >> temp.file

Вот что мы имеем сейчас. Он создает содержимое файла с каждой строкой, заключенной в кавычки.

:clean_install
    echo New installation >> %INSTALL_LOG%

    echo > %INSTALL_FOLDER%"\sql\oracle\table_maintenance_tmp.sql
    for /f "usebackq tokens=* delims=" %%A in (table_maintenance.sql) do (
       call :replace_width_and_write_line "%%A"
    )
    goto done

:replace_width_and_write_line
    echo %1 | find "&&TARGET_STRING" > NUL
    if %ERRORLEVEL% == 0 (
        echo    TABLE_PARTITION_WIDTH CONSTANT NUMBER := 7 ; >> %INSTALL_FOLDER%"\sql\oracle\table_maintenance_tmp.sql 
        goto :eof
    )
    echo %1 >> %INSTALL_FOLDER%"\sql\oracle\table_maintenance_tmp.sql
    goto :eof

Вопрос в том, как мы можем отобразить содержимое строки в файл без кавычек, если строка содержит символы перенаправления? Если это не может быть сделано, то есть другой способ достичь нашей первоначальной цели, которая состоит в том, чтобы взять в качестве входных данных файл, который может содержать или не содержать определенную целевую строку, и создать в качестве выходного файла файл, идентичный исходному файл, за исключением того, что если эта целевая строка существует, она заменяется новой строкой?

Я искал здесь на stackoverflow, и два наиболее полезных вопроса:
* Как вы удаляете кавычки из строки ECHO в пакетном файле Windows?
* Работа с кавычками в пакетных сценариях Windows

Примечание: Пожалуйста, не предлагайте Cygwin, sed, awk, Perl, Python, Ruby, unx или любые другие технологии, которые не поставляются с Windows XP из коробки. Эти ответы будут отклонены.

Спасибо
shoover

Ответы [ 3 ]

2 голосов
/ 21 августа 2009

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

Существует возможность экранирования специальных символов перед печатью строки. Хотя это утомительно и медленно.

Сначала вам нужно указать свою строку в переменной окружения. Используйте кавычки, чтобы не допустить путаницы любых специальных символов:

set "tmp=%~1"

Осторожно ставить кавычки вокруг полного аргумента, а не только части после =, так как в противном случае вы также получите кавычки в переменной.

Затем вы можете начать экранировать специальные символы, один за другим:

set "tmp=%tmp:<=^<%"
set "tmp=%tmp:>=^>%"
set "tmp=%tmp:&=^&%"
set "tmp=%tmp:|=^|%"

и т.д.

Это должно работать, но манипулирование переменными среды довольно медленное, поэтому в больших файлах это будет неинтересно.

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

> set "a=foo <bar> baz"

> set a
a=foo <bar> baz

> echo %a%
The system cannot find the file specified.

> set "a=%a:<=^<%"

> set a
a=foo ^<bar> baz

> set "a=%a:>=^>%"

> set a
a=foo ^<bar^> baz

> echo %a%
foo <bar> baz

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

0 голосов
/ 21 августа 2009

cscript - это стандартный компонент, установленный для Windows.http://en.wikipedia.org/wiki/Windows_Script_Host

Ниже приведен скрипт, который удаляет строки текста, которые будут соответствовать регулярному выражению.Скрипт можно настроить для добавления параметров командной строки для поиска rgx и текста замены.

/*
One part of the script needs to search through a file for a particular string and modify that string.
In bash, this is easy. The approach we are taking in the Windows batch script is to walk through the
file, line by line. If a line does not contain the target string, we echo it to a temp file as-is.
If a line contains the target string, we echo a hardcoded string to the temp file.
*/

/**
 * Usage: type <in.file> | cscript //Nologo test.js > <out.file>
 */
function main() {
    var rgxScrubMatch = /<SpecialInternalTagComment>/;
    var replacement = "safe text";
    scrubLines(rgxScrubMatch, replacement, WScript.StdIn, WScript.StdOut);
}
main();

/**
 * Will echo back line 
 *
 * @param rgxScrubMatch uses replacement on match
 * @param replacement string to replace entire line that matches
 * @param input input stream
 * @param output output stream
 * @return undefined
 */
function scrubLines(rgxScrubMatch, replacement, input, output) {
    while(!input.AtEndOfStream) {
        var line = input.ReadLine();
        if(rgxScrubMatch.test(line)) {
            output.Write(replacement + "\r\n");
        } else {
            output.Write(line + "\r\n");
        }
    }
}
0 голосов
/ 21 августа 2009

Вы можете использовать Edlin.

Из статьи Википедии :

"Его настойчивость, вероятно, может быть объясняется тем, что это может быть вызывается для автоматического выполнения малых изменения в текстовых файлах, по трубам скрипт команд к нему через стандартный ввод. "

Обратите внимание, что он недоступен в 64-битных версиях Окна и длина строки ограничены 253 символами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...