需要解释批处理文件(windows)中“echo”的行为

时间:2017-03-28 15:19:04

标签: batch-file command-line cmd

我的问题是我可以回应我想要的但不是我想要的方式。尽管如此,取决于我如何编写/安排代码,我得到回声以表现各种各样,但从来没有我想要的方式。有人可以解释我发生了什么以及为什么结果是这样,它可能会帮助我理解我应该如何改变我的代码以使其正确。以下是一些解决方案(限于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. 我想要什么
  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!>>%_fileOut%
    
    1. 什么有效,但很慢
    2. 现在我的第一次尝试,这很慢,因为它回显了元素/逗号/元素/逗号......直到回显换行符之前的行尾

      :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. 奇怪的方式回应我想要的和我不做的,而且很慢
      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!
        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
        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的修改
          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:\Users\VerchieD\Desktop\Command_line\example.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:\Users\VerchieD\Desktop\Command_line\output.csv
            SET _fileOut
            SET /P _fileOut=Type input: %=%
            IF NOT DEFINED "%_fileOut%" set "_fileOut=C:\Users\VerchieD\Desktop\Command_line\Output.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
            

2 个答案:

答案 0 :(得分:1)

测试代码

@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!
        )
    )

对于原因部分,速度问题的产生是因为每个管道都会为管道的每一侧产生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

答案 1 :(得分:1)

您的问题令人困惑,缺乏多重细节。虽然您的解释充足且有几个示例,但您从未说过您想要的输出。您已经展示了几个输出的外观,但您没有说过其中一个是正确的,如果没有,那么每种情况下的问题是什么。这样,你的几个代码示例几乎没用......而且,你的问题是与“批处理文件中”echo“的行为有关。”

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

@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%"

回复此代码“无法解决您的问题”。如果我不知道问题是什么,我无法解决问题。

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