Board logo

标题: [文本处理] [已解决]批处理如何根据输入的字符串替换文本里固定行中的固定字符后面4位 [打印本页]

作者: zidha    时间: 2019-8-4 09:38     标题: [已解决]批处理如何根据输入的字符串替换文本里固定行中的固定字符后面4位

本帖最后由 zidha 于 2019-8-5 19:05 编辑

我有一个1.xml文件,想修改文件里固定行数的字符串,如下只截取了一部分:
  1. <component name="Microsoft">
  2.             <ComputerName>PCZF0001</ComputerName>
  3.             <TimeZone>China Standard time</TimeZone>
  4.         </component>
复制代码
我想修改这行 <ComputerName>PCZF0001</ComputerName>的PCZF0001,PCZF001后边的4个数字是不确定的;

需要手动输入,如输入0002,就如下:
<ComputerName>PCZF0002</ComputerName>

如输入0003,就如下:
<ComputerName>PCZF0003</ComputerName>

如输入0999,就如下:
<ComputerName>PCZF0999</ComputerName>

以此类推,如何用批处理修改,先谢谢了。
作者: flashercs    时间: 2019-8-4 10:26

这是改计算机名?
把0001 改为 0004 之类?
作者: zidha    时间: 2019-8-4 10:37

回复 2# flashercs

是的
作者: flashercs    时间: 2019-8-4 11:40

本帖最后由 flashercs 于 2019-8-4 20:36 编辑
  1. @echo off
  2. Powershell -Command "$flag = $false; $sb = $ExecutionContext.InvokeCommand.NewScriptBlock((Get-Content -LiteralPath \"%~0\" | ForEach-Object { if ($flag) { $_ }else { if ($_ -match '#+Powershell#+') { $Script:flag = $true } } }) -join \"`r`n\"); & $sb "
  3. pause
  4. exit /b
  5. ########Powershell########
  6. # XML文件路径
  7. $xmlpath = "E:\test\new folder\zuma\1.xml"
  8. # 计算机名前缀
  9. $prefix = "PCZF"
  10. function MakeDOM {
  11.   param (
  12.    
  13.   )
  14.   $dom = try {
  15.     New-Object -ComObject 'Msxml2.DOMDocument.6.0'
  16.   }
  17.   catch {
  18.     try {
  19.       New-Object -ComObject 'Msxml2.DOMDocument.3.0'
  20.     }
  21.     catch {
  22.       try {
  23.         New-Object -ComObject 'Msxml2.DOMDocument'
  24.       }
  25.       catch {
  26.         throw
  27.       }
  28.     }
  29.   }
  30.   $dom.async = $false
  31.   $dom.validateOnParse = $false
  32.   $dom.resolveExternals = $false
  33.   $dom.setProperty('AllowDocumentFunction', $false)
  34.   $dom.setProperty('AllowXsltScript', $false)
  35.   $dom.setProperty('MaxElementDepth', 256)
  36.   $dom.setProperty('ProhibitDTD', $true)
  37.   $dom.setProperty('SelectionLanguage', 'XPath')
  38.   return $dom
  39. }
  40. function parseError {
  41.   param(
  42.     $dom
  43.   )
  44.   $myErr = $dom.parseError
  45.   if ($myErr.errorCode -ne 0) {
  46.     Write-Host -InputObject "XML parse error" -ForegroundColor Red
  47.     Out-Host -InputObject @{
  48.       'reason'  = myErr.reason;
  49.       'code'    = myErr.errorCode.toUIString(16);
  50.       'filepos' = myErr.filepos;
  51.       'line'    = myErr.line;
  52.       'linepos' = myErr.linepos;
  53.       'srcText' = myErr.srcText;
  54.       'url'     = myErr.url
  55.     }
  56.     return $true
  57.   }
  58.   return $false
  59. }
  60. $xmldoc = MakeDOM
  61. try {
  62.   $xmldoc.load($xmlpath) | Out-Null
  63.   if (parseError $xmldoc) {
  64.     throw
  65.   }
  66.   do {
  67.     $dic = $host.UI.Prompt('Modify XML', '请输入替换前和替换后的字符串:', @('From', 'To'))
  68.     try {
  69.       $xmldoc.SelectSingleNode("//ComputerName[text()=`"$prefix$($dic.From)`"]/text()").nodeValue = $prefix + $dic.To
  70.       Write-Host "Success" -ForegroundColor Green
  71.     }
  72.     catch {
  73.       Write-Host "Failed" -ForegroundColor Green
  74.     }
  75.     $choice = $host.UI.PromptForChoice('继续修改', '是否继续?', @([System.Management.Automation.Host.ChoiceDescription]::new('Y', 'Yes'), [System.Management.Automation.Host.ChoiceDescription]::new('N', 'No')), 0)
  76.   } until ($choice)
  77.   $xmldoc.save($xmlpath)
  78. }
  79. catch {
  80.   
  81. }
  82. finally {
  83.   [System.Runtime.InteropServices.Marshal]::ReleaseComObject($xmldoc) | Out-Null
  84.   Remove-Variable -Name xmldoc
  85.   [gc]::collect()
  86.   [gc]::WaitForPendingFinalizers()
  87. }
复制代码

作者: zidha    时间: 2019-8-4 12:41

flashercs 发表于 2019-8-4 11:40

谢谢你的解答!
我试了下但报错,
  1. True
  2. Modify XML
  3. 请输入需要替换的字符串:
  4. From: 8888
  5. To: 3333
  6. 在此对象上找不到属性“nodeValue”。请确认该属性存在并且可设置。
  7. 所在位置 行:35 字符: 60
  8. + ... .SelectSingleNode("//ComputerName[text()=`"$prefix$($dic.From)`"]/tex ...
  9. +                                                         ~~~~~~~~~
  10.     + CategoryInfo          : InvalidOperation: (:) [],RuntimeException
  11.     + FullyQualifiedErrorId : PropertyNotFound
  12. 请按任意键继续. . .
复制代码
可不可是纯批处理脚本,因为我要在WinPE下运行的;
还有就是最好就是直接修改,不要输入原来字串,因为不能每次使用时打开文件查看一下PCZF后面4个字符。
作者: /zhqsystem/zhq    时间: 2019-8-4 13:49

给你弄个直接创建9999个的吧,用哪个复制哪个,注意格式必须与样本保持一致
示例代码:有些东西和路径自己替换
  1. SetLocal EnableDelayedExpansion
  2. set "component="&&for /f "delims=" %%i in ('type "1.txt"')do if /i "%%i"=="        </component>" (set "component=True")else (
  3.   if defined component (>>".\PCZFxxxx.xml" echo,%%i)
  4. )
  5. for /f "delims=" %%i in ('type "1.txt"')do if /i "%%i"=="        </component>" (
  6.   for /l %%n in (0,1,9999)do (set "#=0000%%n"
  7.    >".\PCZF!#:~-4!.xml" (
  8.     call:1 PCZF!#:~-4!
  9.     type ".\PCZFxxxx.xml"
  10.    )
  11.   )
  12. )
  13. del/q ".\PCZFxxxx.xml"
  14. pause
  15. goto:eof
  16. :1
  17. echo,^<component name="Microsoft"^>
  18. echo,            ^<ComputerName^>%*^</ComputerName^>
  19. echo,            <TimeZone^>China Standard time^</TimeZone^>
  20. echo,        ^</component^>
  21. goto:eof
复制代码

作者: zaqmlp    时间: 2019-8-4 14:16

  1. @echo off
  2. set info=互助互利,支付宝扫码头像,感谢赞助
  3. rem 有问题,可加QQ956535081及时沟通
  4. cd /d "%~dp0"
  5. set "infile=1.xml"
  6. set "outfile=2.xml"
  7. set /p input=输入编号:
  8. for /f "delims=:" %%a in ('findstr /n "<ComputerName>" "%infile%"') do set #%%a=1
  9. (for /f "tokens=1* delims=:" %%a in ('findstr /n .* "%infile%"') do (
  10.     if defined #%%a (
  11.         echo;            ^<ComputerName^>PCZF%input%^</ComputerName^>
  12.     ) else echo;%%b
  13. ))>t.t
  14. move /y t.t "%outfile%"
  15. echo;%info%
  16. pause
复制代码

作者: zidha    时间: 2019-8-4 18:12

回复 6# /zhqsystem/zhq
我要的是修改文件内的字符,不是文件名;我把论坛的“批处理For语句从入门到精通(完整版)”读了一遍也没能在你的文件上修改成功
我是新手,能力有限,7楼的朋友已经帮我解决了,不过还是感谢你的解答。
我找了个批处理但是有些问题如下:
  1. @echo off&setlocal enabledelayedexpansion
  2. ren abc.xml abc.txt
  3. set /p pcname=Name:
  4. for /f "delims=" %%a in (abc.txt) do (
  5.    set /a num+=1
  6.    if !num!==88 (echo "            <ComputerName>!pcname!</ComputerName>") else echo %%a
  7. )>>abc.xml
  8. del  abc.txt
  9. pause
复制代码
修改后的那行总是被添加了两个""如下:
  1. "            <ComputerName>8888</ComputerName>"
复制代码
但去掉就闪退,”“去掉后,文字里的"<”“>”可能被识别成命令符了。
作者: zidha    时间: 2019-8-4 18:17

回复 7# zaqmlp
非常感谢你,这个脚本可以达到我要的结果;
还想请教个问题,直接修改原文件而不生成新文件,需要怎么做,或者指点下需要使用什么命令或哪方面资料吗?
作者: Batcher    时间: 2019-8-4 18:53

回复 9# zidha


7楼14行改成这样试试:
move /y t.t "%infile%"
作者: Batcher    时间: 2019-8-4 18:55

回复 8# zidha


特殊字符可以用^转义试试
http://bbs.bathome.net/thread-1205-1-1.html#pid25363
作者: zidha    时间: 2019-8-4 20:28

回复 10# Batcher

非常感谢!这样是可以的,但中间不生成临时文件可以吗?
作者: flashercs    时间: 2019-8-4 20:33

回复 12# zidha

没有临时文件
  1. @echo off
  2. set "xmlfile=%~dp01.xml"
  3. set /p input=输入编号:
  4. for /f "delims=:" %%a in ('findstr /n "<ComputerName>" "%xmlfile%"') do set #%%a=1
  5. for /f "tokens=1* delims=:" %%a in ('"2>nul,findstr /n .* "%xmlfile%"&&<nul,>"%xmlfile%",set /p="') do (
  6.   if defined #%%a (
  7.         >>"%xmlfile%",echo,            ^<ComputerName^>PCZF%input%^</ComputerName^>
  8.     ) else >>"%xmlfile%",echo,%%b
  9. )
  10. pause
  11. exit /b
复制代码

作者: zidha    时间: 2019-8-4 20:37

回复 11# Batcher

太感谢了,看了“转帖:批处理中符号的作用”再参考7楼的脚本,修改了下我之前的找到脚本也可以达到效果了。
  1. @echo off&setlocal enabledelayedexpansion
  2. ren abc.xml abc.txt
  3. set /p pcname=Name:
  4. for /f "delims=" %%a in (abc.txt) do (
  5.    set /a num+=1
  6.    if !num!==88 (echo             ^<ComputerName^>PCZF!pcname!^</ComputerName^>) else echo %%a
  7. )>>abc.xml
  8. del  abc.txt
  9. pause
复制代码

作者: xczxczxcz    时间: 2019-8-4 21:04

都搞这么复杂?
  1. $enter =Read-Host "输入序号";
  2. $f ="$(gl)\a.xml";
  3. [xml]$file =gc $f -ReadCount 0;
  4. $file.component.ComputerName='FCZF'+$enter;
  5. $file.Save($f);
  6. cmd /c pause
复制代码

作者: Batcher    时间: 2019-8-5 09:22

回复 12# zidha


    容易导致文件内容丢失。不建议那样做。
作者: zidha    时间: 2019-8-5 19:15

回复 15# xczxczxcz


    谢谢!Powershell是很强大,但WinPE下兼容问题不好解决;我把7楼的脚本在WinPE下跑了下,

本地系统测试过的,没问题,就跑出来“findstr”不是内部命令不支持的问题,

最后提取Win10系统里“findstr.exe”文件封进启动映像里才解决。
作者: zidha    时间: 2019-8-5 19:16

回复 16# Batcher


    收到,非常感谢!
作者: WHY    时间: 2019-8-5 20:35

本帖最后由 WHY 于 2019-8-5 20:41 编辑
  1. @echo off
  2. set /p input=input:
  3. (for /f "delims=" %%i in (a.xml) do (
  4.         set "str=%%i"
  5.         setlocal enabledelayedexpansion
  6.         if "!str:<ComputerName>=!" NEQ "!str!" (
  7.                 echo;            ^<ComputerName^>PCZF!input!^</ComputerName^>
  8.         ) else (echo;!str!)
  9.         endlocal
  10. )) > b.xml
  11. move b.xml a.xml
  12. pause
复制代码





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