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

[文本处理] 批处理如何读取php.ini配置文件插入指定内容?

本帖最后由 piazini 于 2025-1-31 21:54 编辑

各位佬们,请教个问题。
php 每次升级,都要配置里面的某些参数(不用老的覆盖是因为怕有新内容注意不到,对比又费事麻烦,版本多的时候一个个对比,不太友好)
这里随便找个参数作为例子:
  1. ; cgi.fix_pathinfo = 0
复制代码
我想在遍历 php.ini-dist 这个文件时,如果发现有。这个字符串
  1. ; cgi.fix_pathinfo = 0
复制代码
那么就把;(封号去掉)或者插入没有;封号开头的内容
  1. cgi.fix_pathinfo = 1
复制代码
想要的结果是,在 php.ini-dist 原有内容基础上,插入 cgi.fix_pathinfo = 1,并生成新文件 php.ini

在for循环时候,会自动把;封号开头的内容过滤掉,所以可能导致下面方法没有成功。
用替换方法,没成功
  1. set "PHP_INI_FILE=php.ini-dist"
  2. for /f "delims=" %%i in ('type "%PHP_INI_FILE%"') do (
  3.             set "line=%%i"
  4.             set "line=!line:%SEARCH_TEXT%=%REPLACE_TEXT%!"
  5.             echo !line!>>"php.ini"
  6. )
复制代码
用if判断方法,没成功
  1. set "PHP_INI_FILE=php.ini-dist"
  2. for /f "delims=" %%i in ('type "%PHP_INI_FILE%"') do (
  3.             set "line=%%i"
  4.             if "!line!" == "%SEARCH_TEXT%" (
  5.                 echo "%REPLACE_TEXT%" >> "%OUTPUT_FILE%"
  6.             )
  7.             echo !line!>>"php.ini"
  8. )
复制代码
所以,请问,这个我要怎么弄才能达到效果

----------------------------------------------------------------------------------------------------------
2025年1月31日 更新:
经过楼下各位佬的解答,脚本功能已经完成。
可以直接跳到53楼查看
或者 点击连接查看
http://www.bathome.net/redirect. ... 0471&pid=287334

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

功能:
   自动解压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

回复 50# aloha20200628


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

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

本帖最后由 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

  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

回复 46# aloha20200628


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

TOP

回复 44# piazini


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

QQ 20147578

TOP

回复 45# piazini

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

TOP

回复 40# aloha20200628


    是的,本来想把样本和源码打包上传附件的,方便大家看到来龙去脉,结果发现上传失败,可能是我的等级低。

    在排查过程中也发现我的问题,也发现 if 里的 %%b 有时候会没有值,有时候又有值,

    不明所以为什么会空值,然后在if前输出%%b后,if又好了能正常判断输出了

    现在不知道调的是不是和延迟变量有关系,输出文本里 所有的叹号又没了

    另,还想问一下,如果有多个替换的值,增做方便些,我能想到就是多加几个if这样判断

    有没有类似python的字典方式的放 查找字符:替换字符?

TOP

回复 41# czjt1234


    新年好,非常感谢回复,目前打算用bat方式解决,而且也不想依赖第三方东西,这样在各版本系统中,都可以直接使用。

   目前编写bat系统是Win11 等写好后打算去 Win7 上验证一下

TOP

回复 39# 77七


    打印了目录,确实发现,路径不对,解决了,谢谢

TOP

可还行
if exist 是使用变量的值判断文件 , 不是判断变量本身 , 变量是变量 , 文件是文件
执行 set file=win12.iso 并不会拥有win12的iso文件了 , 只会拥有值为win12.iso的变量

还是不行不如直接用记事本打开 , 然后查找替换

TOP

  1. rem 另存为 ANSI 编码 bat
  2. ' & cls & cscript.exe /nologo /e:vbscript "%~f0" %* & pause & exit /b
  3. PHP_INI_FILE = "php.ini-dist"
  4. SEARCH_TEXT  = "; cgi.fix_pathinfo = 0"
  5. REPLACE_TEXT = "cgi.fix_pathinfo = 1"
  6. OUT_FILE     = "php.ini"
  7. Set oStream = CreateObject("ADODB.Stream")
  8. oStream.Type = 2
  9. oStream.Mode = 3
  10. oStream.Charset = "GBK"
  11. oStream.Open()
  12. oStream.LoadFromFile PHP_INI_FILE
  13. s = oStream.ReadText()
  14. oStream.Close()
  15. m = Replace(SEARCH_TEXT, " ", "")
  16. m = Replace(m, ".", "\.")
  17. Pattern = "^"
  18. If Left(m, 1) = ";" Then
  19.     Pattern = Pattern & "; *"
  20.     m = Right(m , Len(m) - 1)
  21. End If
  22. m = Split(m, "=")
  23. Pattern = Pattern & m(0) & " *= *" & m(1)
  24. Set oRegExp = CreateObject("VBScript.RegExp")
  25. oRegExp.Global = True
  26. oRegExp.MultiLine = True
  27. oRegExp.IgnoreCase = True
  28. oRegExp.Pattern = Pattern
  29. If oRegExp.Test(s) Then s = oRegExp.Replace(s, REPLACE_TEXT)
  30. oStream.Open()
  31. oStream.WriteText s
  32. oStream.SaveToFile OUT_FILE, 2
  33. oStream.Close()
复制代码
不知道5楼的powershell楼主为什么不用,win7、win10、win11都是自带powershell.exe的,很方便

这个是批处理调用cscript.exe,也是winxp、win7、win10、win11自带的命令
这里做了兼容性处理
SEARCH_TEXT指定为以下几行都可以得到同样的结果
; cgi.fix_pathinfo = 0
;  cgi.fix_pathinfo  =  0
;cgi.fix_pathinfo=0
cgi.fix_pathinfo = 0

QQ 20147578

TOP

本帖最后由 aloha20200628 于 2025-1-29 22:29 编辑

回复 36# piazini

如果仅是解决一楼的问题,用14楼代码完全可以结帖了
但楼主 实际要解决的问题和实际采用的代码 并非完全如此,这就很容易把解答者带入 ‘迷阵’...

TOP

返回列表