[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
回复 45# piazini

   复盘一下本帖》你虽然明示了要处理的数据文件是 php.ini-dist,但始终不知道你实际测试采用的完整代码,如果及时贴出来的话,大家会对你不断丢出的 ‘奇怪问题’ 早就一目了然了...
   至于在批处代码中可否实现类似python字典替换的问题,须提供一个示例来明确表述...

TOP

回复 44# piazini


winxp、win7、win10、win11系统自带的命令
不是第三方命令

QQ 20147578

TOP

回复 46# aloha20200628


    是的,我回顾整个过程,也单独运行你写的程序,和你说的效果一样。
    然后,我又反复查看,分析了一下。定位到了问题,在代码某个for循环里使用了延迟变量,用错了结束延迟语句,endlocal,
    正确的是 setlocal disabledelayedexpansion 而且,我还放错了地方,for 循环里有个if判断,满足会跳出,结果我放到跳出后关闭延迟变量,相当于没有关闭延迟变量。

TOP

  1. set "INPUT_FILE_529_dev=php.ini-dist"
  2. set "INPUT_FILE_541_dev=php.ini-development"
  3. set "PHP_INI_FILE=php.ini-development"
  4. if "%INPUT_FILE_529_dev%" == "%PHP_INI_FILE%" (
  5.         @REM 替换v5.2.9版 dev 的 php.ini-dist 文件内容
  6.         set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
  7.         set "REPLACE_TEXT=cgi.fix_pathinfo=1"
  8.         (for /f "tokens=1* delims=:" %%a in ('findstr /n ".*" %PHP_INI_FILE%') do (
  9.             if /i "%%b"=="%SEARCH_TEXT%" (echo,%SEARCH_TEXT% & echo,%REPLACE_TEXT%) else echo,%%b
  10.         ))>"%OUTPUT_FILE%"
  11. ) else if  "%INPUT_FILE_541_dev%" == "%PHP_INI_FILE%" (
  12.     @REM 替换v5.4.1版 dev 的 php.ini-development 文件内容
  13.     set "SEARCH_TEXT=;cgi.fix_pathinfo=1"
  14.     set "REPLACE_TEXT=cgi.fix_pathinfo=1"
  15.     (for /f "tokens=1* delims=:" %%a in ('findstr /n ".*" %PHP_INI_FILE%') do (
  16.         echo b=%%b
  17.         echo SEARCH_TEXT=%SEARCH_TEXT%
  18.         echo REPLACE_TEXT=%REPLACE_TEXT%
  19.         if /i "%%b"=="%SEARCH_TEXT%" (echo,%REPLACE_TEXT%) else echo,%%b
  20.     ))>"%OUTPUT_FILE%"
  21. )
复制代码
又遇到新问题,按照 set 设置变量,走的 else if 语句,但是打印 SEARCH_TEXT 变量值,确是 ; cgi.fix_pathinfo=0 (也就是 if 里变量值),难道同名变量不能覆盖?

TOP

本帖最后由 aloha20200628 于 2025-1-31 15:04 编辑

回复 49# piazini

   这是新手在同一cmd进程窗口中多次调试同一批处脚本的常见错误,根本原因是还未了解cmd的 ‘预处理’ 机制 》简言之就是对那些用&连接或用()包裹的 ‘复合语块’ (典型如 if... 和 for...)在被实际执行前,会将其中的所有 %var% 变量预先赋值,而无视所在语块中已有的赋值命令。
   因此,49楼代码第一次运行后留存的 %SEARCH_TEXT% 变量值会在代码第二次运行时被 ‘预处理’ 预先赋值给所有复合语块中的 %SEARCH_TEXT% 变量,从而出现楼主报告的 ‘奇怪’ 现象。
   最简洁的解决方法至少有两个,一是全程采用延迟变量,但这会拦截文件读取的!字符,除非改用分段管理延迟变量的对策,但如此代码量会增加;
   二是要在脚本头部(即所有复合语块之前)对其后不同复合语块中引用的 %SEARCH_TEXT% 和 %REPLACE_TEXT% 分别赋值,例如
   set "SEARCH_TEXT529=; cgi.fix_pathinfo=0"
   set "REPLACE_TEXT529=cgi.fix_pathinfo=1"
   set "SEARCH_TEXT541=;cgi.fix_pathinfo=1"
   set "REPLACE_TEXT541=cgi.fix_pathinfo=1"
   其后再调整相应复合语块中的引用变量名即可。

TOP

回复 14# aloha20200628


    把14楼代码放到 if 里,执行就不成功了。
    双击执行时或直接在命令行打开 bat 时,第7行 echo %PHP_INI_FILE% 行提示 ECHO 处于关闭状态。正常应该是打印输出量值
    奇怪,为什么写到 if 里的语句和写在 if 外的结果不一样。
    包括 set /p 接受用户参数也一样,if 外 set /p 接受用户参数,直接用%%号包括变量就能echo输出,但是在 if 里,需要用延迟变量,用!!包裹才能显示。

    我写的如下:
  1. @echo off
  2. if ""=="" (
  3.     set "PHP_INI_FILE=php-5.2.9-Win32\php.ini-dist"
  4.     set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
  5.     set "REPLACE_TEXT=cgi.fix_pathinfo=1"
  6.     echo %PHP_INI_FILE%
  7.     echo "PHP_INI_FILE=%PHP_INI_FILE%"
  8.     echo "SEARCH_TEXT=%SEARCH_TEXT%"
  9.     echo "REPLACE_TEXT=%REPLACE_TEXT%"
  10.     (for /f "tokens=1* delims=:" %%a in ('findstr /n ".*" %PHP_INI_FILE%') do (
  11.         if /i "%%b"=="%SEARCH_TEXT%" (echo,%REPLACE_TEXT%) else echo,%%b
  12.     ))>"php-5.2.9-Win32\php.ini"
  13. )
  14. exit/b
复制代码

TOP

回复 50# aloha20200628


    嗯嗯,明白了,你说的延迟变量还没想到咋写。但是第二个明白了,就是把局部变量写道开头部分成全局变量。
    bat 写起来比 linux shell 的坑多太多了。

TOP

感谢大家的解答,脚本功能完成了。把我写的和大家帮助完成的功能,全部完整分享出来,方便更多人。

功能:
   自动解压php的zip 压缩包,并自动读取php模板文件,开启 CGI 和 ext 扩展目录
   要解压的php压缩包名,可以输入,也可以拖动 zip 到 bat脚本上,自动获取文件名和路径
使用环境:
   需要安装 winrar 或 7zip (需要其他压缩软件,请自己在源码里添加)
测试环境:
   Win11
   php 压缩包 v5.2.9 :https://museum.php.net/php5/php-5.2.9-Win32.zip
   php 压缩包 v5.4.1 : https://windows.php.net/downloads/releases/archives/php-5.4.1-Win32-VC9-x86.zip
   (选用这两个版本原因是,php.ini 模板文件名在5.4.1版本开始有了变化)

因为内容长度限制,也没 法上传附件,我把源码放到下面路径里,大家有兴趣自己看吧:
https://www.cnblogs.com/wutou/p/18695979

再次感谢大家的帮助,谢谢。

TOP

返回列表