不一致“命令的语法不正确”错误

时间:2015-09-11 22:08:28

标签: batch-file windows-7 heisenbug variable-expansion

我想我一开始就疯狂地使用批处理文件,但这个问题让我撕裂了我的头发!以下批处理脚本通常可以正常工作。但是,在第一次运行时,它将给出“命令的语法不正确”错误;它将执行此操作,直到我REM输出所有内容,然后运行它,然后取消REM它。然后它神奇地再次开始工作!

@echo off

REM Create processed data directory
set "PROCDIR=processed"
mkdir %PROCDIR% 2>nul

REM Loop through CSV files and process them
for %%f in (*.csv) do (
  set "in=%%~nf"
  set "input=%%~nxf"
  set "out_lang=%PROCDIR%\%in%_lang.csv"
  set "out_spr=%PROCDIR%\%in%_spr.csv"
  set "out_ajt=%PROCDIR%\%in%_ajt.csv"

  echo Processing %input%

  REM Split input file appropriately
  REM FIXME Hardcoded line ranges are brittle
  sed -n "1,2p"  %input% > %out_lang%
  sed -n "3,55p" %input% > %out_spr%.tmp
  sed -n "56,$p" %input% > %out_ajt%.tmp

  REM Unpack SPR data
  REM n.b., Needs gawk 4, or later
  gawk -f spr.awk %out_spr%.tmp > %out_spr%
  del %out_spr%.tmp

  REM Substitute AJT data values
  REM n.b., -i seems to be buggy in Windows
  sed -f ajt.sed %out_ajt%.tmp > %out_ajt%
  del %out_ajt%.tmp
)

如果我REM@echo off,它似乎失败了,因为变量替换有时 - 由于未知原因 - 不起作用。然后,当它到达sed时,它就会放弃。

我认为我错过了一些东西......任何想法都可能是什么!? (除了我的弹珠!)

2 个答案:

答案 0 :(得分:2)

如果我可以提供建议,请使用并滥用PAUSE命令,ECHO并在其中转义字符^。还有Ctrl-C在PAUSE期间停止脚本。

这是一个调试版本:

@echo off

SETLOCAL
REM Create processed data directory
set "PROCDIR=processed"
echo mkdir %PROCDIR% 2^>nul

REM Loop through CSV files and process them
for %%F in (*.csv) do (
  set "in=%%~nF"
  echo in: %in%
  set "input=%%~nxF"
  echo input: %input%
  set "out_lang=%PROCDIR%\%in%_lang.csv"
  set "out_spr=%PROCDIR%\%in%_spr.csv"
  set "out_ajt=%PROCDIR%\%in%_ajt.csv"

  echo Processing %input%
PAUSE

  REM Split input file appropriately
  REM FIXME Hardcoded line ranges are brittle
  echo sed -n "1,2p"  %input% ^> %out_lang%
  echo sed -n "3,55p" %input% ^> %out_spr%.tmp
  echo sed -n "56,$p" %input% ^> %out_ajt%.tmp
PAUSE

  REM Unpack SPR data
  REM n.b., Needs gawk 4, or later
  echo gawk -f spr.awk %out_spr%.tmp ^> %out_spr%
  echo del %out_spr%.tmp
PAUSE

  REM Substitute AJT data values
  REM n.b., -i seems to be buggy in Windows
  echo sed -f ajt.sed %out_ajt%.tmp ^> %out_ajt%
  echo del %out_ajt%.tmp
PAUSE

)
ENDLOCAL
GOTO :EOF
EXIT /B 0

我添加了setlocal enabledelayedexpansion,这似乎解决了未声明的变量错误。

以下是工作版本(您必须删除所有多余的echo和插入符号^):

@echo off
setlocal enabledelayedexpansion

REM Create processed data directory
set "PROCDIR=processed"
echo mkdir %PROCDIR% 2^>nul

REM Loop through CSV files and process them
for %%F in (*.csv) do (
  set "in=%%~nF"
  echo in: !in!
  set "input=%%~nxF"
  echo input: !input!
  set "out_lang=!PROCDIR!\!in!_lang.csv"
  set "out_spr=!PROCDIR!\!in!_spr.csv"
  set "out_ajt=!PROCDIR!\!in!_ajt.csv"

  echo Processing !input!
PAUSE

  REM Split input file appropriately
  REM FIXME Hardcoded line ranges are brittle
  echo sed -n "1,2p"  !input! ^> !out_lang!
  echo sed -n "3,55p" !input! ^> !out_spr!.tmp
  echo sed -n "56,$p" !input! ^> !out_ajt!.tmp
PAUSE

  REM Unpack SPR data
  REM n.b., Needs gawk 4, or later
  echo gawk -f spr.awk !out_spr!.tmp ^> !out_spr!
  echo del !out_spr!.tmp
PAUSE

  REM Substitute AJT data values
  REM n.b., -i seems to be buggy in Windows
  echo sed -f ajt.sed !out_ajt!.tmp ^> !out_ajt!
  echo del !out_ajt!.tmp
PAUSE

)
endlocal
GOTO :EOF
EXIT /B 0

答案 1 :(得分:1)

Stephan是正确的,由于未在 FOR 循环中使用延迟扩展,批处理代码无效。

@echo off
setlocal EnableDelayedExpansion
REM Create processed data directory
set "PROCDIR=processed"
mkdir "%PROCDIR%" 2>nul

REM Loop through CSV files and process them
for %%f in (*.csv) do (
  set "in=%%~nf"
  set "input=%%~nxf"
  set "out_lang=%PROCDIR%\!in!_lang.csv"
  set "out_spr=%PROCDIR%\!in!_spr.csv"
  set "out_ajt=%PROCDIR%\!in!_ajt.csv"

  echo Processing !input!

  REM Split input file appropriately
  REM FIXME Hardcoded line ranges are brittle
  sed -n "1,2p"  "!input!" >"!out_lang!"
  sed -n "3,55p" "!input!" >"!out_spr!.tmp"
  sed -n "56,$p" "!input!" >"!out_ajt!.tmp"

  REM Unpack SPR data
  REM n.b., Needs gawk 4, or later
  gawk -f spr.awk "!out_spr!.tmp" >"!out_spr!"
  del "!out_spr!.tmp"

  REM Substitute AJT data values
  REM n.b., -i seems to be buggy in Windows
  sed -f ajt.sed "!out_ajt!.tmp" >"!out_ajt!"
  del "!out_ajt!.tmp"
)
endlocal

( ... )定义的块中引用的每个环境变量都由命令处理器在解析整个块时进行扩展。在其中一个帮助页面上,在执行if /?时输出到命令提示符窗口,详细说明了这一点。

在没有第一行的命令提示符窗口中运行有问题的批处理代码时可以看到这一点。在没有echo offecho on的命令提示符窗口中运行批处理文件应该用于调试批处理代码不能按预期工作。

如果当前目录中的任何CSV文件在文件名中包含1个或多个空格,则必须用双引号括起所有文件引用,以便为这些文件提供工作代码。