需要解释批处理文件(窗口)中"echo"的行为



我的问题是我可以回显我想要的东西,但不能按照我想要的方式回显。尽管如此,根据我编写/排列代码的方式,我会得到 echo 的行为,而不是我想要的方式。有人可以解释我正在发生的事情以及为什么结果是这样的,这可能会帮助我理解我应该如何更改我的代码以使其正确。以下是一些解决方案(限制为 5 个)以及它的行为方式(循环涉及第二行的回声):

我要回显的矩阵元素是(2行,逗号拆分列)

, rim_no , account_no , observation_date , observation_month , start_date , maturity_date , days_past_due , rate , spread 
1, 2517, 1000008332, 20160831, 201608, NA, NA, 0, 17, 0
  1. 我想要什么

当它到达此循环时,它只需退出并关闭命令窗口

:EchoData
SET _var=""
FOR /L %%H IN (0,1,%_colonne%) DO (
if %%H equ 0 set _var=!_matrice[%_ligneAct%][%%H]!
set _help=!_var!
if %%H gtr 0 set _var=!_help!, !_matrice[%_ligneAct%][%%H]!
)
echo !_var!>>%_fileOut%
  1. 什么有效但很慢

现在我的第一次尝试,它很慢,因为它回显元素/逗号/元素/逗号......直到回显换行之前行尾

:EchoData
SET _var=""
FOR /L %%H IN (0,1,%_colonne%) DO (
echo|set /p=!_matrice[%_ligneAct%][%%H]!>>%_fileOut%
if not %%H equ %_colonne% echo|set /p=,>>%_fileOut%
if %%H equ %_colonne% echo.>>%_fileOut% 
)

输出看起来像

, rim_no , account_no , observation_date , observation_month , start_date , maturity_date , days_past_due , rate , spread 
1 , 2517 , 1000008332 , 20160831 , 201608 , NA , NA , 0 , 17 , 0 
  1. 奇怪的方式,既回响了我想要的,又回响了我不想要的,而且很慢

另一个确实有效的尝试,两次回显结果,第一行慢速,第二行快速

:EchoData
SET _var=""
FOR /L %%H IN (0,1,%_colonne%) DO (
if %%H equ 0 set _var=!_matrice[%_ligneAct%][%%H]!
set _help=!_var!
if %%H gtr 0 set _var=!_help!, !_matrice[%_ligneAct%][%%H]!
echo !_var!
echo|set /p=!_matrice[%_ligneAct%][%%H]!>>%_fileOut%
if not %%H equ %_colonne% echo|set /p=,>>%_fileOut%
if %%H equ %_colonne% echo.>>%_fileOut%
)
echo !_var!>>%_fileOut%

输出看起来像

, rim_no , account_no , observation_date , observation_month , start_date , maturity_date , days_past_due , rate , spread 
1 , 2517 , 1000008332 , 20160831 , 201608 , NA , NA , 0 , 17 , 0 
1, 2517, 1000008332, 20160831, 201608, NA, NA, 0, 17, 0 
  1. 奇怪的方式 2

另一种奇怪的方式,用逗号回响行,然后是我的第二行的两倍

:EchoData
SET _var=""
FOR /L %%H IN (0,1,%_colonne%) DO (
if %%H equ 0 set _var=!_matrice[%_ligneAct%][%%H]!
set _help=!_var!
if %%H gtr 0 set _var=!_help!, !_matrice[%_ligneAct%][%%H]!
echo !_var!
if not %%H equ %_colonne% echo|set /p=,>>%_fileOut%
if %%H equ %_colonne% echo.>>%_fileOut%
if %%H equ %_colonne% echo|set /p=!_var!>>%_fileOut%
if %%H equ %_colonne% echo.>>%_fileOut%
)
echo !_var!>>%_fileOut%   

输出看起来像

, rim_no , account_no , observation_date , observation_month , start_date , maturity_date , days_past_due , rate , spread 
, , , , , , , , , 
1, 2517, 1000008332, 20160831, 201608, NA, NA, 0, 17, 0 
1, 2517, 1000008332, 20160831, 201608, NA, NA, 0, 17, 0
  1. 奇怪方式2的修改

当注释一行时,它只是退出脚本并且不回显任何内容......

:EchoData
SET _var=""
FOR /L %%H IN (0,1,%_colonne%) DO (
if %%H equ 0 set _var=!_matrice[%_ligneAct%][%%H]!
set _help=!_var!
if %%H gtr 0 set _var=!_help!, !_matrice[%_ligneAct%][%%H]!
echo !_var!
::if not %%H equ %_colonne% echo|set /p=,>>%_fileOut%
if %%H equ %_colonne% echo.>>%_fileOut%
if %%H equ %_colonne% echo|set /p=!_var!>>%_fileOut%
if %%H equ %_colonne% echo.>>%_fileOut%
)
echo !_var!>>%_fileOut% 
Basically, I expected solutions 2,3,4 to behave as they do.
I would expect solutions 1 and 5 to behave differently (do not get what is wrong)...
Especially, I do not get why 3 and 4 do work but not 5 and 1. Is it something to do with the echo| set /p?
One more thing is that when echoing the slow way, element by element, it keeps returning "The system cannot find the drive specified".

为了澄清起见,我在这里添加了完整的代码(输入文件是上面提到的文件,在我的例子中是csv):

@ECHO off
SETLOCAL EnableDelayedExpansion
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::Adress of the input and output files
GOTO InFile
:FalseIN 
ECHO You need to enter a valid location for the source file. 
GOTO InFile
:InFile
ECHO Please enter the location of your file in like C:UsersVerchieDDesktopCommand_lineexample.csv
SET _fileIn
SET /P _fileIn=Type input: %=%
IF NOT EXIST "%_fileIn%" GOTO FalseIn
ECHO The selected input file to work with is %_fileIn%
:OutFile
echo Please enter the name of your output like C:UsersVerchieDDesktopCommand_lineoutput.csv
SET _fileOut
SET /P _fileOut=Type input: %=%
IF NOT DEFINED "%_fileOut%" set "_fileOut=C:UsersVerchieDDesktopCommand_lineOutput.csv"
ECHO.>"%_fileOut%"
ECHO The selected output file to work with is %_fileOut%
ECHO stop 1
@PAUSE
SET _countParse=0
SET _countParseBis=0
SET _countNext=0
SET _countNextBis=0
SET _ligneAct=0
SET _ligne=0
SET _colonne=0
CALL :ParseHeader "%_fileIn%"
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
GOTO :eof
::Parse input file header, first element
:ParseHeader
SET /a _countParse+=1
SET _list=%1
SET _list=%_list:"=%
FOR /F "tokens=1* delims=, " %%a IN ('TYPE "%_list%"') DO (
set _matrice[%_ligne%][%_colonne%]=%%a
set /a _colonne+=1
if not "%%b"=="" call :ParseHeaderBis "%%b"
)
GOTO :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
GOTO :eof
::Parse input file header, from second element onward
:ParseHeaderBis
SET /a _countParseBis+=1
SET _list=%1
SET _list=%_list:"=%
FOR /F "tokens=1* delims=, " %%a IN ("%_list%") DO (
set _matrice[%_ligne%][%_colonne%]=%%a
if not "%%b"=="" set /a _colonne+=1
if not "%%b"=="" if %_ligne% equ 0 call :ParseHeaderBis "%%b"
if "%%b"=="" set /a _ligne+=1
)
@PAUSE
IF %_ligne% gtr 0 GOTO :EchoHeader 
GOTO :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::Echoes one element at a time for now, will be changed
:EchoHeader
FOR /L %%H IN (0,1,%_colonne%) DO (
::echo The column %%H 
::echo variable is !_matrice[0][%%H]!
echo|set /p=!_matrice[0][%%H]!>>%_fileOut%
if not %%H equ %_colonne% echo|set /p=,>>%_fileOut%
if %%H equ %_colonne% echo.>>%_fileOut%
)
@PAUSE
CALL :Next 
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
GOTO :eof
::Parse input file data, from second row onward, get lines
:Next
SET /a _countNext+=1
SET /a _ligneAct=%_ligne%
SET _colonne=0
FOR /F "skip=%_ligne% tokens=* delims=" %%a IN ('type "%_fileIn%"') DO (
if not "%%a"=="" call :NextBis "%%a"
if "%%a"=="" goto :eof
)
GOTO :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
GOTO :eof
::Parse the lines from the input file
:NextBis
SET /a _countNextBis+=1
SET _list=%1
SET _list=%_list:"=%
FOR /F "tokens=1* delims=, " %%a IN ("%_list%") DO (
set _matrice[%_ligne%][%_colonne%]=%%a
if not "%%b"==""  set /a _colonne+=1
if not "%%b"==""  if %_ligne% equ %_ligneAct%  call :NextBis "%%b"
if "%%b"==""  set /a _ligne+=1 
)
IF %_ligne% gtr %_ligneAct% GOTO :EchoData 
GOTO :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:EchoData
::SET _var=""
::FOR /L %%G IN (0,1,%_ligneAct%) DO (
::FOR /L %%H IN (0,1,%_colonne%) DO (
::echo The row %%G 
::echo and column %%H 
::echo value is !_matrice[%%G][%%H]!
::if %%H equ 0 set _var=!_matrice[%_ligneAct%][%%H]!
::set _help=!_var!
::if %%H gtr 0 set _var=!_help!, !_matrice[%_ligneAct%][%%H]!
::echo|set /p=!_matrice[%_ligneAct%][%%H]!>>%_fileOut%
::if not %%H equ %_colonne% echo|set /p=,>>%_fileOut%
::if %%H equ %_colonne% echo.>>%_fileOut%
::if %%H equ %_colonne% echo|set /p=!_var!>>%_fileOut%
::if %%H equ %_colonne% echo.>>%_fileOut%
::if %%H==0 (set "_var=!_matrice[%_ligneAct%][%%H]!") else (set "_var=!_var!, !_matrice[%_ligneAct%][%%H]!")
::echo !_var!
::)
::)
:: for /l %%c in (0 1 %col%) do (
::     if %%c==0 ( set "line=!_M[%%r,%%c]!" ) else ( set "line=!line!, !_M[%%r,%%c]!" )
:: )
:: echo !line!
>%_fileOut% (
::for /l %%r in (0 1 %row%) do (
set "line="
for /l %%c in (0 1 %_colonne%) do (
if %%c==0 ( set "line=!_matrice[%_ligneAct%][%%c]!" ) else ( set "line=!line!, !_matrice[%_ligneAct%][%%c]!" )
)
echo !line!
::)
)
::echo !_var!>>%_fileOut%
@PAUSE
CALL :Next
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:eof
@PAUSE

测试代码

@echo off
setlocal enableextensions enabledelayedexpansion
rem Populate "matrix" 
set "row=-1"
for %%r in (
"# ,rim_no , account_no , observation_date , observation_month , start_date , maturity_date , days_past_due , rate , spread" 
"1, 2517, 1000008332, 20160831, 201608, NA, NA, 0, 17, 0"
) do (
set /a "row+=1", "col=-1"
for %%c in (%%~r) do (
set /a "col+=1"
set "_matrice[!row!][!col!]=%%c"
)
)
rem Dump "matrix" to output file
> "outputFile.txt" (
for /l %%r in (0 1 %row%) do (
set "line="
for /l %%c in (0 1 %col%) do (
if %%c==0 ( set "line=!_matrice[%%r][%%c]!" ) else ( set "line=!line!, !_matrice[%%r][%%c]!" )
)
echo !line!
)
)

对于 Why 部分,速度问题之所以产生,是因为每个管道都会为管道的每个侧面生成一个cmd进程。此外,重定向每个操作会使进程变慢,因为它将打开/写入/关闭每个操作的输出文件。只需重定向整个过程。

输出中有重复项,因为您通过set /p或直接回显相同的信息不止一次echo

对于5的情况,您不得使用::注释代码块内的行,请使用rem

编辑代码更新为遵循(多于更多)原始代码

@echo off
setlocal enableextensions enabledelayedexpansion
set "inputFile=input.csv"
set "outputFile=output.csv"
rem Populate "matrix" 
set "row=-1"
for /f "usebackq delims=" %%l in ("%inputFile%") do (
set /a "row+=1", "col=-1"
set "line=%%l"
call :splitLine
)
rem Dump "matrix" to output file
> "%outputFile%" (
for /l %%r in (0 1 %row%) do (
set "line="
for /l %%c in (0 1 %col%) do for /f "delims=" %%x in ("!_matrice[%%r][%%c]!") do (
if %%c==0 ( set "line=%%x" ) else ( set "line=!line!, %%x" )
)
echo !line!
)
)
type "%outputFile%"
goto :eof
:splitLine
(for /f "tokens=1* delims=, " %%a in ("!line!") do if not "%%a"=="" (
set /a "col+=1"
set "_matrice[!row!][!col!]=%%a"
set "line=%%b"
)) && goto :splitLine || goto :eof

您的问题令人困惑,缺少多个细节。虽然你的解释很充分,有几个例子,但你从来没有说过你想要的输出是什么。您已经展示了几个输出的外观,但您没有说其中一个是否正确,如果不是,每种情况下的问题是什么。这样,您的几个代码示例实际上毫无用处......另外,您的问题与"批处理文件中的"回显"行为"无关。

出于这个原因,我只是在这里展示了一个通用方法的示例,当元素用空格和/或逗号分隔时,从输入文件中读取二维矩阵(如您的数据示例),并将这样的矩阵输出到输出文件:

@ECHO off
SETLOCAL EnableDelayedExpansion
set "_fileIn=input.txt"
set "_fileOut=output.txt"
rem Read the matrice line by line from the input file
SET /A _ligne=0
for /F "usebackq delims=" %%a in ("%_fileIn%") do (
rem Separate all fields in this line and store they in the next matrice row
set /A _ligne+=1, _colonne=0
for %%b in ( %%a ) do (
set /A _colonne+=1
set _matrice[!_ligne!][!_colonne!]=%%b
)
)
rem Write all matrice lines to the output file
(for /L %%G in (1,1,%_ligne%) do (
rem Initialize the next output line
set "_var="
rem Join to it all elements in this matrice row
for /L %%H in (1,1,%_colonne%) do set "_var=!_var! , !_matrice[%%G][%%H]!"
rem Show the line
echo !_var!
)) > "%_fileOut%"

请不要回复此代码"不能解决您的问题"。如果我不知道问题是什么,我就无法解决问题。

如果您分析该程序的输出并确定与所需输出的差异,也许我们可以修复代码......

最新更新