Эхо-текст с окончаниями строк Unix из пакетного сценария Windows (.bat)

Скажем, у меня есть следующий пакетный скрипт:

For ... DO (
SET VAL=%%B
IF defined VAL echo %%A=%%B >> %OUTPUT_FILEPATH%
)

Как я могу получить echo для вывода с использованием окончаний строк Unix (только перевод строки)?

В качестве альтернативы, могу ли я записать файл как есть, а затем преобразовать его из пакетного сценария? (как-то найти /r/n и заменить на /n? Если да, то как мне это сделать?)

Мне нужно автономное решение (то есть такое, которое не требует загрузки дополнительных утилит и может быть выполнено из самого пакетного сценария [Windows 7]).


person simonalexander2005    schedule 25.11.2016    source источник
comment
Я был удивлен, что не смог найти это, уже заданное где-то на SO.   -  person simonalexander2005    schedule 25.11.2016
comment
Преобразование текстовых файлов в разрывы строк в стиле Unix на самом деле не что иное, как вывод каждой строки без завершающего разрыва строки, за которым следует явно выводимый символ перевода строки.; следовательно, вы можете найти что-то полезное при поиске чего-то вроде эха без символа новой строки и новой строки...   -  person aschipfl    schedule 25.11.2016
comment
В Интернете много информации о преобразовании текстового файла Windows в unix. Если у вас есть моя утилита обработки текста регулярных выражений JREPL.BAT , то вы можете записать файл в обычном режиме, а затем использовать call jrepl "^" "" /u /f yourFile.txt /o -. Или вы можете использовать конвейер для записи файла непосредственно в формате unix: yourCommandThatGeneratesFile | jrepl "^" "" /u /o yourFile.txt.   -  person dbenham    schedule 25.11.2016
comment
@dbenham: я не понимаю, как ваш jrepl "^" "" ... может работать. Регулярное выражение "^" является якорем, соответствующие позиции; он не соответствует символам (поэтому он не может их исключить) и, в любом случае, он соответствует началу строк, а не концу, как требуется...   -  person Aacini    schedule 26.11.2016
comment
@Aacini - это что-то вроде взлома. Пара «найти/заменить» намеренно не действует. Важным битом является опция /U, которая записывает все строки с терминатором \n вместо \r\n. Мне просто нужна была неразрушающая пара поиска/замены. Загрузка JREPL только для преобразования текста в форму unix нелепа. Но это полезный инструмент для многих других ситуаций, и если он у вас уже есть, то он может быть эффективным и действенным инструментом для этого преобразования. Я написал решение JREPL как комментарий вместо ответа именно потому, что это хак.   -  person dbenham    schedule 26.11.2016


Ответы (3)


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

Форматировать сложно, но попробуйте

set ^"LF=^

^" Don't remove previous line & rem line feed (newline)
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"& rem Define newline with line continuation

For ... DO (
SET VAL=%%B
IF defined VAL <nul set/P^=%%A=%%B%\n%>> %OUTPUT_FILEPATH%
)

Или, чтобы избежать начального пробела после первой строки:

<nul set/P^=%%A=%%B%\n%^>> %OUTPUT_FILEPATH%
person elzooilogico    schedule 25.11.2016
comment
сложно может быть хорошим преуменьшением ....... есть ли шанс, что вы могли бы уточнить, что это делает в вашем ответе? - person simonalexander2005; 25.11.2016
comment
@simonalexander2005 извините, это не мой родной язык. в зависимости от того, что будет в %%A или %%B, может быть много символов для экранирования, таких как set/p ^= - person elzooilogico; 25.11.2016
comment
Нет необходимости избегать = в set/P^=. Измените синтаксис на set /P ="%%A=%%B%\n%", чтобы (окружающие) кавычки больше не терялись. Однако ведущие пробелы всегда будут теряться. Обратите внимание, что ведущие знаки = вызывают синтаксическую ошибку. На самом деле нет безопасного способа использования set /P, но есть другие методы - см. этот ответ. Или вы переключаетесь на другой язык... - person aschipfl; 25.11.2016
comment
@simonalexander2005 — лучшее объяснение %\n% можно найти по адресу stackoverflow.com/a/6379861/1012053 (где jeb называет это %NL% вместо этого.). <nul set /p=... — это часто используемый прием для написания текста без новой строки в конце, но у него есть ограничения. - person dbenham; 25.11.2016
comment
@dbenham спасибо, в ваших комментариях всегда что-то новое! хороший пост читать! - person elzooilogico; 25.11.2016
comment
Я только что понял, что ваше определение \n не совсем правильно для этого приложения - оно расширяется до наличия ^ в конце для продолжения строки, что нежелательно. Лучшее определение — set ^"\n=^^^%LF%%LF%^%LF%%LF%" (просто удалите замыкающую пару ^^ в конце исходного присваивания). - person dbenham; 25.11.2016

Подходящий способ выполнить это преобразование — не через пакетный файл, а с помощью другого языка программирования, например JScript; таким образом, процесс преобразования является быстрым и надежным. Однако вам не нужна программа из сотен строк, чтобы добиться такой простой замены. Двухстрочный пакетный файл ниже выполняет это преобразование:

@set @a=0 /* & cscript //nologo //E:JScript "%~F0" < input.txt > output.txt & goto :EOF */

WScript.Stdout.Write(WScript.Stdin.ReadAll().replace(/\r\n/g,"\n"));

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

@set @a=0 /*

@echo off
set "OUTPUT_FILEPATH=C:\Path\Of\The\File.txt"
cscript //nologo //E:JScript "%~F0" < "%OUTPUT_FILEPATH%" > output.txt
move /Y output.txt "%OUTPUT_FILEPATH%"

goto :EOF */

WScript.Stdout.Write(WScript.Stdin.ReadAll().replace(/\r\n/g,"\n"));

Первая строка — это уловка, которая скрывает команду cscript из кода JScript, поэтому при компиляции этого гибридного файла .BAT не возникает ошибок.

В коде JScript: WScript.Stdin.ReadAll() прочитать весь перенаправленный входной файл; это может вызвать проблемы, если файл огромный. Метод replace использует регулярное выражение, чтобы определить текст для замены и поместить на его место вторую строку; вы можете прочитать дальнейшее описание этой темы по адресу этой ссылка. WScript.Stdout.Write просто берет результат замены и отправляет его на экран. Легкий! Не так ли? ;-)

person Aacini    schedule 25.11.2016
comment
+1, но я не уверен во фразе правильно?! Я бы предпочел увидеть фразу вроде разумный способ. Трудно утверждать, что пакетный метод, который работает, неверен. Но я бы тоже использовал JScript, скорее всего через JREPL, учитывая, что он уже есть в моей библиотеке приемов. Я предпочитаю использовать построчную обработку, потому что JScript ограничен максимальным размером, который он может прочитать в одну строку. Чтение по одной строке почти устраняет проблему размера. - person dbenham; 25.11.2016
comment
@dbenham: Ну, иногда я не выбираю лучший термин. Я изменил его подходящим способом... - person Aacini; 26.11.2016
comment
вы говорите отправить его на экран - как я могу получить его в свой выходной файл (тот же самый, из которого он читал?) вместо этого? не могли бы вы привести пример, относящийся к моему сценарию? Итак, у меня есть файл (хранящийся в %OUTPUT_FILEPATH%) — как мне заменить окончания в этом файле вашим методом? - person simonalexander2005; 28.11.2016
comment
Как вы можете видеть в коде, часть > output.txt перенаправляет вывод на экран из JScript в файл output.txt, поэтому после этого вам просто нужно добавить команду move /Y output.txt %OUTPUT_FILEPATH%... Я соответствующим образом изменил код. - person Aacini; 28.11.2016

Если вы согласны с использованием PowerShell, вы можете создать новую строку Unix следующим образом:

PowerShell -Command Write-Host

Вы можете комбинировать это с трюком SET /P для вывода текста без новых строк и добавлять новые строки вручную. Например:

( ECHO | SET /P="Hello World!" & PowerShell -Command Write-Host ) > output.txt

После этого output.txt будет содержать текст Hello World! с добавлением одного символа 0x0a.

person Matus Horvath    schedule 27.01.2020