Первое решение использует:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F delims^=^ eol^= %%B in ('%*') do (
set "data=%%B"
set "data=!data:|=!"
echo(!data!
)
endlocal
tokens=*
приводит к присвоению переменной цикла B
всей строки с удаленными начальными пробелами / табуляциями, в то время как delims=
приводит к присвоению переменнойпеременная цикла B
вся строка, включая начальные пробелы / табуляции.Поэтому определение пустого списка разделителей в целом лучше.
FOR по умолчанию игнорирует пустые строки, а строки, начинающиеся с точки с запятой, поскольку ;
по умолчанию интерпретируются как конецсимвол строкиПо этой причине необычная строка опции, не заключенная в двойные кавычки delims^=^ eol^=
, используется здесь для определения пустого списка разделителей и без символа конца строки.Символ каретки ^
используется для экранирования следующего символа, чтобы он интерпретировался как буквальный символ, а не как разделитель аргументов, хотя и не заключен в строку аргумента с двойными кавычками.
Но есть одна проблема с этим решением:Строка, содержащая один или несколько восклицательных знаков !
, не обрабатывается корректно, поскольку командный процессор Windows интерпретирует в командной строке set "data=%%B"
каждый !
как начало / конец отложенной ссылки на переменную среды и заменяет строку между двумя восклицательными знаками натекущее значение переменной окружения с этим именем или без нее в переменной, не существующей с таким именем, и удаляет все после !
, если больше нет !
.
Существует как минимум три решения.
Первый включает и отключает отложенное расширение в цикле.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F delims^=^ eol^= %%B in ('%*') do (
set "data=%%B"
setlocal EnableDelayedExpansion
set "data=!data:|=!"
echo(!data!
endlocal
)
endlocal
Пожалуйста, прочитайте этот ответ для получения подробной информации о командах SETLOCAL и ENDLOCAL , поскольку они делают гораздо больше, чем простовключение / выключение отложенного расширения в цикле.
(
между echo
и значением переменной среды data
используется в случае, если строка содержит только |
без или с дополнительными пробелами /табуляция data
становится либо неопределенной, либо строкой, состоящей только из пробелов / табуляций.Пробел между echo
и !data!
будет при исполнении только команды echo
с пропущенным пробелом и 0 или более пробелов / табуляций, что приведет к получению вывода ECHO is off.
вместо пустой строки или строки с только пробелами /вкладки.Открывающая круглая скобка предотвращает это и интерпретируется cmd.exe
как разделитель между командой echo
и строкой ее аргумента, которая в этом случае всегда начинается с (
. ECHO игнорирует первый символ строки аргумента на выходе, если строка аргумента не /?
и, следовательно, (
никогда не выводится.
Второе решение использует подпрограмму:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F delims^=^ eol^= %%B in ('%*') do (
set "data=%%B"
call :ProcessLine
)
endlocal
goto :EOF
:ProcessLine
set "data=%data:|=%"
echo(%data%
goto :EOF
Примечание: echo %data%
может привести к неожиданному поведению, если строка содержит символы, такие как операторы перенаправления <
и >
или оператор &
для WindowsКомандный процессор выполняет echo(%data%
после замены %data%
текущей строкой переменной среды data
.Даже set "data=%data:|=%"
может быть проблематичным в зависимости от строки, содержащей "
и <>&
.Таким образом, это решение на самом деле небезопасно.
См. Также Куда возвращается GOTO: EOF?
Третье решение использует ссылку на переменную среды с двойным процентом ииспользование команды CALL для принудительного двойного анализа командной строки, содержащей %%variable%%
вместо обычного %variable%
.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F delims^=^ eol^= %%B in ('%*') do (
set "data=%%B"
call set "data=%%data:|=%%"
call echo(%%data%%
)
endlocal
Примечание Также это решениене совсем безопасно в зависимости от данных, как второе решение.
См. также Как интерпретатор сценариев команд Windows (CMD.EXE) анализирует?
Командный процессор Windowsпредназначен для выполнения команд и приложений, а не для переформатирования или обработки CSV файлов с использованием вертикальной черты в качестве разделителя / разделителя.
Для понимания используемых команд и их работы откройте окно командной строкивыполните там следующие команды и внимательно прочитайте все страницы справки, отображаемые для каждой команды.
call /?
echo /?
endlocal /?
for /?
goto /?
set /?
setlocal /?
И читать также ответ на Почему не выводится строка с «echo% var%» после использования «set var = text» в командной строке? по причине использования синтаксиса set "variable=value"
вместо set variable=value
или set variable="value"
.