【问题标题】:Batch file add/remove hosts file entries syntax error批处理文件添加/删除主机文件条目语法错误
【发布时间】:2012-02-23 01:35:36
【问题描述】:

以下脚本用于管理在 hosts 文件中添加和删除条目。带有 .dev 的条目应该指向 localhost,所有其他条目都应该提示输入 IP 地址。如果条目已经存在,它应该询问您是否要删除它。

我收到一个模糊的 The syntax of the command is incorrect 错误,但我不确定它指的是哪一行。如果我打开@echo 然后在下一行吐出if ( 然后死掉。我能捕捉到错误的唯一方法是截屏,因为它会立即退出。

我已经为此花费了几个小时,因此将不胜感激任何帮助!

@echo off

title ClearSight Studio
echo Virtual website setup script
echo Version 1.4
echo Last modified 12/30/2011
echo.

REM Get the name of the domain name
echo What domain name? Ctrl+C to cancel. Example: newdomain.dev.
set /p domain= Domain:

REM Set a variable for the Windows hosts file location
set hostpath=\windows\system32\drivers\etc
set hostfile=hosts
set sitespath=\clearsight\sites
set extension=%domain:~-3%

REM Make the hosts file writable
attrib -r %hostpath%\%hostfile%

REM Add the domain to point to localhost at the end of the file if it doesn't already have an entry.
find /c "   %domain%" %hostpath%\%hostfile%
if errorlevel 1 (
    if /i %extension%==dev (
        set /p ip= What is the IP?
    )
    echo. >> %hostpath%\%hostfile%
    echo.# Adding %domain% via batch process on %date:~10,4%-%date:~4,2%-%date:~7,2%. >> %hostpath%\%hostfile%
    if %ip% (
        echo.%ip%       %domain% >> %hostpath%\%hostfile%
    ) else (
        echo.127.0.0.1      %domain% >> %hostpath%\%hostfile%
    )
) else if errorlevel 0 (
    echo Entry found in hostfile already. Would you like to remove it?
    set /p remove= Remove (Y/N)
    if /i %remove%==Y (
        findstr /v "%domain%" %hostpath%\%hostfile% > %hostpath%\%hostfile%
    )
)

if /i %extension%==dev (
    REM Create the folder if it doesn't exist
    if exist %sitespath%\%domain% (
        echo %sitespath%\%domain% already exists.
    ) else (
        echo Creating %sitespath%\%domain%...
        mkdir %sitespath%\%domain%
    )
)

REM Clean up
attrib +r %hostpath%\%hostfile%

echo. 
echo Done. 

if /i %extension%==dev (
    REM Do a "git" of the repo, if requested
    echo Would you like to clone an external git repository named %domain% from Bitbucket?
    echo This assumes the git repository was set up under the "jamonholmgren" account.
    echo Do it manually if it's under someone else's account. Also, make sure you have permissions to this repo.
    set /p getgit= Get git clone? (Y/N):
)

REM 
if /i %getgit%==Y (
    git clone git@bitbucket.org:jamonholmgren/%domain%.git %sitespath%\%domain%\
    pause
) else (
    echo Okay, then we're done.
    pause
)

【问题讨论】:

    标签: dos batch-file


    【解决方案1】:

    这段代码有两个问题

    if %ip% (
        echo.%ip%       %domain% >> %hostpath%\%hostfile%
    ) else (
    
    • 语法无效。我假设您想测试变量是否已定义。正确的语法是if defined ip (

    • 您正试图在定义 %ip% 的同一 if() 块中展开它。这是行不通的,因为 %ip% 是在解析时展开的,也就是在您分配值之前!解决方案是使用延迟扩展而不是!ip!。必须首先启用延迟扩展,可能在脚本顶部附近,使用 setlocal enableDelayedExpansion

    所以固定的代码看起来像这样

    setlocal enableDelayedExpansion
    .
    .
    .
    if defined ip (
        echo.!ip!       %domain% >> %hostpath%\%hostfile%
    ) else (
    

    %remove% 存在同样的延迟扩展问题

    编辑 - 扩展 Andriy M 的评论

    您在处理用户输入的 ip 和删除方面也存在潜在问题。在提示输入值之前,这两个值都应初始化为空值或默认值。如果用户没有输入任何内容,则保留现有的默认值(如果有)。

    此外,您可能需要确认输入的值是否有效,尤其是对于 ip。如果你这样做了,那么你会想要把提示从循环中取出,并将它放在一个被调用的子例程中。该子例程可以检查是否输入了一个值,如果没有输入则循环返回以重试。它必须在子例程中,因为您不能像使用 IF 语句那样在带括号的代码块中 GOTO。

    【讨论】:

    • 我认为ip 也必须在开头的某处未定义(可能在setlocal … 之后),只是为了在调用if defined ip … 时安全起见,以防用户按下无需输入任何内容即可进入。
    • @AndriyM - 是的,我看到了。我认为验证输入的值可能比初始化值更重要。我偷懒了,没说,但我现在修改答案。
    【解决方案2】:

    当您通过 %variable% 扩展变量值时,它的值仅在读取包含命令的行之后和执行命令之前扩展一次。例如:

    set var=Original
    set var=New & echo %var%
    

    上一行显示“原始”。用括号括起来的任何命令(属于任何 IF 或 FOR 命令)都会发生相同的效果。

    解决这个问题的方法是使用延迟变量扩展,用感叹号而不是百分号括起来:

    set var=Original
    set var=New & echo !var!
    

    但是,您必须首先使用以下命令激活延迟扩展:

    setlocal EnableDelayedExpansion
    

    因此,在程序开头插入前一行,并更改所有对变量的引用,这些变量可能会在 IF 或 FOR 中通过 !name 更改其值!而不是 %name%。例如:

    if %ip% (
    

    我确定是导致您的问题的线路...

    【讨论】:

      【解决方案3】:

      感谢大家的帮助!这是最终(工作)结果,以防有人想做类似的事情。屏幕输出可能需要稍作调整,但在我所有的测试中,它似乎完全可靠。

      @echo off
      setlocal enableDelayedExpansion
      
      title ClearSight Studio
      echo Virtual website setup script
      echo Version 1.5
      echo Last modified 2/23/2012
      echo.
      
      REM Get the name of the domain name
      echo What domain name? Ctrl+C to cancel. Example: newdomain.dev.
      set /p domain= Domain: 
      
      REM Set a variable for the Windows hosts file location
      set hostpath=\windows\system32\drivers\etc
      set hostfile=hosts
      set sitespath=\clearsight\sites
      set extension=%domain:~-3%
      REM Make the hosts file writable
      attrib -r %hostpath%\%hostfile%
      
      REM Add the domain to point to localhost at the end of the file if it doesn't already have an entry.
      find /c "   %domain%" %hostpath%\%hostfile%
      if errorlevel 1 (
          if /i NOT %extension%==dev (
              set /p ip= What is the IP? 
          ) else (
              set ip=127.0.0.1
          )
          echo. >> %hostpath%\%hostfile%
          echo.# Adding %domain% via batch process on %date:~10,4%-%date:~4,2%-%date:~7,2%. >> %hostpath%\%hostfile%
          echo.!ip!       %domain% >> %hostpath%\%hostfile%
      ) else if errorlevel 0 (
          echo Entry found in hostfile already.
          set /p remove= Would you like to remove it? (Y/N) 
          if /i !remove!==Y (
              findstr /v %domain% %hostpath%\%hostfile% > %hostpath%\%hostfile%.txt
              type %hostpath%\%hostfile%.txt > %hostpath%\%hostfile%
          )
      )
      
      if /i %extension%==dev (
          REM Create the folder if it doesn't exist
          if exist %sitespath%\%domain% (
              echo %sitespath%\%domain% already exists.
          ) else (
              echo Creating %sitespath%\%domain%...
              mkdir %sitespath%\%domain%
          )
      )
      
      REM Clean up
      attrib +r %hostpath%\%hostfile%
      
      REM Flush DNS so the changes are available imidiately
      ipconfig /flushdns
      
      echo. 
      echo Done. 
      
      if /i %extension%==dev (
          REM Do a "git" of the repo, if requested
          echo Would you like to clone an external git repository named %domain% from Bitbucket?
          echo This assumes the git repository was set up under the "jamonholmgren" account.
          echo Do it manually if it's under someone else's account. Also, make sure you have permissions to this repo.
          set /p getgit= Get git clone? (Y/N) 
      )
      
      REM 
      if /i !getgit!==Y (
          git clone git@bitbucket.org:jamonholmgren/%domain%.git %sitespath%\%domain%\
          pause
      ) else (
          echo Okay, then we're done.
          pause
      )
      

      【讨论】:

        【解决方案4】:

        只是一些调试批处理文件的提示:

        • cmd shell 启动它以避免退出后关闭窗口

        • 添加更多 REM 命令,这些命令将在转向 echo on 时用作日志条目

        • 通过重复从末尾删除部分直到它运行没有错误来简化脚本。重新插入故障部件并尝试找出问题所在

        虽然这并不能完全回答您的问题,但我希望这些提示可以帮助您解决问题。随时欢迎您寻求一般性建议,但恐怕您的特定问题有点过于具体,无法引起普遍关注。

        【讨论】:

          猜你喜欢
          • 2019-02-26
          • 1970-01-01
          • 2016-04-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-18
          相关资源
          最近更新 更多