Board logo

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

作者: piazini    时间: 2025-1-21 23:02     标题: 批处理如何读取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
作者: Five66    时间: 2025-1-22 00:05

for /f 默认忽略分号开头的行 使用eol选项换成其他
例如换成忽略问号(?)开头的行
for /f "eol=? delims=" ........
作者: 77七    时间: 2025-1-22 00:09

; cgi.fix_pathinfo = 0cgi.fix_pathinfo = 1
来自不同的文本?请按 a 文本 b 文本,及希望得到的c 文本,给出一个例子吧
作者: aloha20200628    时间: 2025-1-22 10:51

回复 1# piazini

订正一楼第二段代码如下
  1. @echo off &setlocal
  2. set "PHP_INI_FILE=php.ini-dist"
  3. set "SEARCH_TEXT=; cgi.fix_pathinfo = 0"
  4. set "REPLACE_TEXT=cgi.fix_pathinfo = 1"
  5. (for /f "eol=╟ delims=" %%i in (%PHP_INI_FILE%) do (
  6.     if /i "%%i"=="%SEARCH_TEXT%" (echo,%REPLACE_TEXT%) else echo,%%i
  7. ))>"php.ini"
  8. pause&exit/b
复制代码

作者: WHY    时间: 2025-1-22 11:57

本帖最后由 WHY 于 2025-1-22 13:36 编辑

PowerShell "(gc 1.txt) -replace '^; *(?=cgi.fix_pathinfo *=)'"
作者: piazini    时间: 2025-1-22 16:57

回复 2# Five66
没有要忽略的行,就是如果没有我想替换的字符串,那么原始的ini内容就全部写到新的ini文件里
作者: piazini    时间: 2025-1-22 16:58

回复 3# 77七
不想修改原始文件,就想读取 原始文件内容,把要替换的字符串替换了,然后生成新文件
作者: piazini    时间: 2025-1-22 17:00

回复 4# aloha20200628
eol=╟ 和  (echo,%REPLACE_TEXT%) 没看懂。

eol 为啥要忽略的是╟ ?
echo 后不是空格显示内容么?
作者: piazini    时间: 2025-1-22 17:01

回复 5# WHY

谢谢,但是想用 bat 实现
作者: aloha20200628    时间: 2025-1-22 17:13

回复 8# piazini

eol=╟  找一个键盘可见字符之外的一个 ascii 非控制字符就是了...
echo,... 只是一个习惯用法,避免用空格可能会导致系统报错(当输出值为空时)

作者: aloha20200628    时间: 2025-1-22 17:48

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


复查了 dostips.com 的老帖,发现彻底取消 eol= 参数及其默认值的一个妙招,可用其重写4楼代码如下...
  1. @echo off
  2. set "PHP_INI_FILE=php.ini-dist"
  3. set "SEARCH_TEXT=; cgi.fix_pathinfo = 0"
  4. set "REPLACE_TEXT=cgi.fix_pathinfo = 1"
  5. (for /f "delims="eol^= %%i in (%PHP_INI_FILE%) do (
  6. if /i "%%i"=="%SEARCH_TEXT%" (echo,%REPLACE_TEXT%) else echo,%%i
  7. ))>"php.ini"
  8. pause&exit/b
复制代码

作者: WHY    时间: 2025-1-24 08:45

bat相关的 "奇技淫巧",这个论坛多的是。前提是你愿意翻、愿意学。
http://bbs.bathome.net/thread-15748-1-8.html
作者: piazini    时间: 6 天前 12:45

回复 11# aloha20200628


    ;封号开头的内容保留成功了,但是 空行和要替换的字符串没成功
作者: aloha20200628    时间: 6 天前 13:44

本帖最后由 aloha20200628 于 2025-1-27 15:56 编辑

回复 13# piazini

以下代码会保留源文件中的空行,此法同时会避免 ‘分号起始行’ 问题...
楼主切记:代码中的 %SEARCH_TEXT% 变量值须确保是从源文件中全行复制过来
  1. @echo off
  2. set "PHP_INI_FILE=php.ini-dist"
  3. set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
  4. set "REPLACE_TEXT=cgi.fix_pathinfo=1"
  5. (for /f "tokens=1* delims=:" %%a in ('findstr /n ".*" %PHP_INI_FILE%') do (
  6.     if /i "%%b"=="%SEARCH_TEXT%" (echo,%REPLACE_TEXT%) else echo,%%b
  7. ))>"php.ini"
  8. pause&exit/b
复制代码

作者: aloha20200628    时间: 6 天前 13:59

本帖最后由 aloha20200628 于 2025-1-27 16:15 编辑

回复 13# piazini

    再给一个 bat+sed 版本(存为 test.bat 运行)以供参考》其中 sed.exe 可从本坛第三方下载,落地即用,与批处脚本同目录 (http://bcn.bathome.net/s/tool/index.html?key=sed
    用 sed.exe 处理文本文件,没有空行和分号起始行等问题...
  1. @echo off & setlocal
  2. set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
  3. set "REPLACE_TEXT=cgi.fix_pathinfo=1"
  4. sed.exe "s/%SEARCH_TEXT%/%REPLACE_TEXT%/gi" "php.ini-dist">"php.ini"
  5. pause&exit/b
复制代码

作者: piazini    时间: 6 天前 14:16

本帖最后由 piazini 于 2025-1-27 14:20 编辑

回复 14# aloha20200628
谢谢你,这么快就回答我问题。以为快过年了,都忙着了。

for 里是 %%a 而if 是 %%b 是写错了?
空行保留了,但是前面有了行号。
来源字符串也是从源文件里复制粘贴到bat脚本里的,但是还是不行。

我在这个贴子http://www.bathome.net/redirect. ... 6383&pid=173035
也看到保留空行方式了,和你一样
作者: piazini    时间: 6 天前 14:18

回复 15# aloha20200628


    喜欢用原生的东西,换环境不用额外装东西,不过也非常感谢提醒
作者: aloha20200628    时间: 6 天前 14:24

回复 16# piazini

14楼代码中就是要用 %%b
再问你的真实替换关键词包含中文吗? 源文件是 ansi 编码还是 utf-8 编码?

作者: Five66    时间: 6 天前 14:41

本帖最后由 Five66 于 2025-1-27 15:56 编辑

找个不会出现在行开头的字符作为eol值
开头是行号,其实不用eol也行
已编辑
  1. @echo off
  2. set "PHP_INI_FILE=php.ini-dist"
  3. set "SEARCH_TEXT=; cgi.fix_pathinfo = 0"
  4. set "REPLACE_TEXT=cgi.fix_pathinfo = 1"
  5. (
  6. for /f "delims=" %%i in ('findstr /n .* "%PHP_INI_FILE%"') do (
  7. set "line=%%i"
  8. setlocal enabledelayedexpansion
  9. set "line=!line:*:=!"
  10. if /i "!line!" == "!SEARCH_TEXT!" (
  11. echo(!REPLACE_TEXT!||/ ^)
  12. ) else (
  13. echo(!line!||/ ^)
  14. )
  15. endlocal
  16. )
  17. )>"php.ini"
  18. pause&exit/b
复制代码

作者: piazini    时间: 6 天前 14:46

回复 18# aloha20200628
没有任何中文,下面是我的代码 :
  1. set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
  2.         set "REPLACE_TEXT=cgi.fix_pathinfo = 1"
  3.         (for /f "delims=" %%i in ('findstr /n ".*" %PHP_INI_FILE%') do (
  4.             if /i "%%i"=="%SEARCH_TEXT%" (echo,%REPLACE_TEXT%) else echo,%%i
  5.         ))>"%OUTPUT_FILE%"
复制代码
要替换的%SEARCH_TEXT%内容,是从php-5.2.9-Win32 文件夹的 php.ini-dist 里复制出来的,VScode 显示是 UTF-8的编码

附件不能上传,你可以到 这个链接下载文件:https://museum.php.net/php5/php-5.2.9-Win32.zip
作者: aloha20200628    时间: 6 天前 14:58

本帖最后由 aloha20200628 于 2025-1-27 15:00 编辑

回复 21# piazini

21楼代码第一行 set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
而1楼中的原值是 ; cgi.fix_pathinfo = 0
这两者有差别! 你确认哪个为真?再将真值替换进14楼代码相应位置就是了...

作者: piazini    时间: 6 天前 15:26

本帖最后由 piazini 于 2025-1-27 15:36 编辑

回复 22# aloha20200628

新版本的 等号两边是有空格的,是我在后来用了老版本的测试,导致描述不一致,抱歉。

那就先用 ; cgi.fix_pathinfo=0 这个来示例说明把。
现在空行是可以保留了,但是:替换还是没成功,而且文件里只要是 !叹号的地方,都被替换成空了

我也没有权限上传图片

结果到98%,马上和我 想要的结果一样了。
作者: Five66    时间: 6 天前 15:58

帮楼主发个个php.ini-dist文件
不知行否
https://gofile.io/d/v1V6Os
作者: aloha20200628    时间: 6 天前 16:06

本帖最后由 aloha20200628 于 2025-1-27 16:44 编辑

回复 22# piazini

用以下两行订正了14楼代码
set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
set "REPLACE_TEXT=cgi.fix_pathinfo=1"
再用20楼所附下载文件中的 php.ini-dist (ansi 编码或 utf-8 编码皆可,共1284行)测试已经顺利通过(输出文件 php.ini 在第520行已被正确修改,1284行输出,其中 ! 字符没有丢失...)

作者: 77七    时间: 6 天前 16:36

本帖最后由 77七 于 2025-1-27 16:37 编辑

楼主应该不单单只替换某一个,而是一些吧?从楼主提供的文件中选取了写代码需要注意的行,还需要明确等号前后的空格需要保留原文本的格式,还是替换成新的固定格式?
  1. [PHP]
  2. ;;;;;;;;;;;
  3. ; Directive names are *case sensitive* - foo=bar is different from FOO=bar.
  4. ;
  5. ; |        bitwise OR
  6. ; &        bitwise AND
  7. ; !        boolean NOT
  8. engine = On
  9. ; Allow the <? tag.  Otherwise, only <?php and <script> tags are recognized.
  10. precision    =  12
  11. ;output_handler =
  12. zlib.output_compression = Off
  13. ; *NOT* affected by whether Safe Mode is turned On or Off.
  14. ; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's
  15. ; cgi.fix_pathinfo=0
  16. ;fbsql.default_user = "_SYSTEM"
  17. soap.wsdl_cache_dir="/tmp"
复制代码

作者: piazini    时间: 4 天前 17:36

回复 24# aloha20200628


    新年快乐
    测试了一下,部分行中间的谈行被保留了,但是行尾的叹号还是被去掉了,如:113、193、316、401、772、807行都被去掉了。
    关键是我的还没替换成功
  1. set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
  2.         set "REPLACE_TEXT=cgi.fix_pathinfo=1"
  3.         (for /f "tokens=1* delims=:" %%a in ('findstr /n ".*" %PHP_INI_FILE%') do (
  4.             if /i "%%b"=="%SEARCH_TEXT%" (echo,%REPLACE_TEXT%) else echo,%%b
  5.         ))>>"%OUTPUT_FILE%"
复制代码

作者: piazini    时间: 4 天前 17:40

回复 25# 77七
新年好
这个配置文件里,去掉配置前的;封号就是开启某个设置值。
我希望的是保留源格式的情况下,去掉前面的封号或在后面插入对应的值。
但是目前还是没达到我想要的效果
不排除后期有多个值要去掉封号,但是目前连一个值前去掉封号都没成功。
作者: piazini    时间: 4 天前 17:42

回复 23# Five66


    新年好,感谢感谢
作者: Five66    时间: 4 天前 18:39

啊,楼主1楼例子的内容=号两边有空格
但是php.ini-dist里的=号两边是没有空格的
将19代码SEARCH_TEXT和REPLACE_TEXT =号两边的空格去掉 , 然后试试
作者: piazini    时间: 4 天前 18:50

回复 29# Five66


    新年好,去掉了也没成功,奇怪了
作者: Five66    时间: 4 天前 18:52

回复 30# piazini
  1. @echo off
  2. set "PHP_INI_FILE=php.ini-dist"
  3. set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
  4. set "REPLACE_TEXT=cgi.fix_pathinfo=1"
  5. (
  6. for /f "delims=" %%i in ('findstr /n .* "%PHP_INI_FILE%"') do (
  7. set "line=%%i"
  8. setlocal enabledelayedexpansion
  9. set "line=!line:*:=!"
  10. if /i "!line!" == "!SEARCH_TEXT!" (
  11. echo(!REPLACE_TEXT!||/ ^)
  12. ) else (
  13. echo(!line!||/ ^)
  14. )
  15. endlocal
  16. )
  17. )>"php.ini"
  18. pause&exit/b
复制代码

作者: aloha20200628    时间: 4 天前 19:04

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

回复 26# piazini

24楼报告结果表明用14楼代码处理20楼所附 'php-5.2.9-Win32.zip' 中的 php.ini-dist 文件(该文件是ansi编码,1284行,没有中文字符,仅在第520行出现被替换字段)已经顺利通过
处理结果是第520行被正确替换,且全文中的 ! 字符均得以保留(包括113、193、316、401、772、807行中的 ! 字符)因为14楼代码全程没有开启延迟变量,字符串包含的 ! 字符不会被转义求值...
楼主采用的全部测试代码中除了14楼代码还有其他前置代码吗?被测试的是这个 php-5.2.9-Win32.zip' 中的 php.ini-dist 文件吗

作者: 77七    时间: 4 天前 19:50

回复 27# piazini


   新年好!  代码前如果有其它代码 开启了延迟变量扩展,需关闭
  1. @echo off
  2. set "file=D:\php-5.2.9-Win32\php.ini-dist"
  3. rem a对应b,不需要空格
  4. set "#"a"=b"
  5. set "#"cgi.fix_pathinfo"=1"
  6. rem 替换为空值,则值为 / 在21行判断,如
  7. set "#"c"=/"
  8. (for /f "tokens=1* delims=:" %%a in ('findstr /n .* "%file%"') do (
  9. if "%%b" neq "" (
  10. for /f "delims==" %%c in (" %%b") do (
  11. for /f "tokens=1* delims=; " %%d in ("%%c") do (
  12. if defined #"%%d" (
  13. if "%%e" equ "" (
  14. for /f "tokens=* delims=; " %%f in (" %%b#") do (
  15. for /f "tokens=1* delims==" %%g in ("%%f") do (
  16. for /f "tokens=*" %%i in ("%%h") do (
  17. set str=%%f
  18. setlocal enabledelayedexpansion
  19. if "!#"%%d"!" equ "/" (
  20. echo=%%g=
  21. ) else (
  22. call echo=!str:%%i=%%#"%%d"%%!
  23. )
  24. endlocal
  25. set m_e=1
  26. )
  27. )
  28. )
  29. )
  30. )
  31. )
  32. )
  33. )
  34. if defined m_e (
  35. set m_e=
  36. ) else (
  37. echo=%%b
  38. )
  39. )) > "out.txt"
  40. rem move "out.txt" "%file%"
  41. pause
复制代码

作者: aloha20200628    时间: 4 天前 20:43

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

回复 26# piazini

再改用另一个方法替换处理 php.ini-dist 文件,楼主可试试以下代码,存为 test.bat 运行,与 php.ini-dist 文件同目录 ...
  1. @echo off &endlocal &setlocal
  2. set "PHP_INI_FILE=php.ini-dist"
  3. set "SEARCH_TEXT=; cgi.fix_pathinfo=0"
  4. set "REPLACE_TEXT=cgi.fix_pathinfo=1"
  5. for /f "tokens=1 delims=:" %%a in ('findstr /n ".*" "%PHP_INI_FILE%"^|findstr /ic:"%SEARCH_TEXT%" ') do set "_#%%a=1"
  6. (for /f "tokens=1* delims=:" %%a in ('findstr /n ".*" %PHP_INI_FILE%') do (
  7.     if defined _#%%a (echo,%REPLACE_TEXT%) else echo,%%b))>"php.ini"
  8. pause&exit/b
复制代码

作者: piazini    时间: 4 天前 21:07

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

回复 33# 77七


    我确实开启了延迟变量,但是遇到个问题,在if exist 前用endlocal关闭了延迟变量,但是"%INPUT_FILE_52_dev%" 为什么会成空值?
    我用%%包裹的变量也会收到影响?
  1.    set "INPUT_FILE_52_dev=php.ini-dist"
  2.    setlocal enabledelayedexpansion
  3.     <略 去一些其他代码>
  4.    endlocal
  5.    @REM 获取配置文件
  6.     set PHP_INI_FILE=
  7.     if exist "%INPUT_FILE_52_dev%" (
  8.         set PHP_INI_FILE="%INPUT_FILE_52_dev%"
  9.     ) else if exist "%INPUT_FILE_dev%" (
  10.         set PHP_INI_FILE="%INPUT_FILE_dev%"
  11.     ) else (
  12.         echo. & echo.
  13.         echo [ Error ] 没有匹配的 dev 版 ini 配置文件:%PHP_INI_FILE% !!!
  14.         echo. & echo. & pause & exit /b
  15.     )
复制代码
输出结果:
  1. [ Error ] 没有匹配的 dev 版 ini 配置文件: !!!
复制代码

作者: piazini    时间: 4 天前 21:17

回复  piazini

24楼报告结果表明用14楼代码处理20楼所附 'php-5.2.9-Win32.zip' 中的 php.ini-dist 文件 ...
aloha20200628 发表于 2025-1-29 19:04


33楼给了提示,可能和我开启延迟变量有关系。但是在没有用到叹号包裹的地方关闭延迟变量,%%包裹的变量会出现空值。
作者: 77七    时间: 4 天前 21:20

回复 35# piazini


   setlocal和endlocal之间设置的变量为区域变量
作者: piazini    时间: 4 天前 21:33

回复 37# 77七

是我描述的问题,变量设置不在延迟变量的范围。
35楼内容修改了,麻烦你再看看
作者: 77七    时间: 4 天前 21:57

回复 38# piazini


   如果用相对路径,检查下脚本的工作目录
作者: aloha20200628    时间: 4 天前 22:11

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

回复 36# piazini

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

作者: czjt1234    时间: 4 天前 22:48

  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
作者: Five66    时间: 4 天前 22:58

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

还是不行不如直接用记事本打开 , 然后查找替换
作者: piazini    时间: 4 天前 23:01

回复 39# 77七


    打印了目录,确实发现,路径不对,解决了,谢谢
作者: piazini    时间: 4 天前 23:04

回复 41# czjt1234


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

   目前编写bat系统是Win11 等写好后打算去 Win7 上验证一下
作者: piazini    时间: 4 天前 23:16

回复 40# aloha20200628


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

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

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

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

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

    有没有类似python的字典方式的放 查找字符:替换字符?
作者: aloha20200628    时间: 3 天前 13:58

回复 45# piazini

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

作者: czjt1234    时间: 3 天前 20:21

回复 44# piazini


winxp、win7、win10、win11系统自带的命令
不是第三方命令
作者: piazini    时间: 3 天前 22:56

回复 46# aloha20200628


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

  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 里变量值),难道同名变量不能覆盖?
作者: aloha20200628    时间: 前天 14:47

本帖最后由 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"
   其后再调整相应复合语块中的引用变量名即可。

作者: piazini    时间: 前天 15:40

回复 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
复制代码

作者: piazini    时间: 前天 16:11

回复 50# aloha20200628


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

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

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

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




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2