批处理或VB脚本,用一个文本文件中的字符串更新(或添加)字符串

时间:2014-02-12 00:01:25

标签: string batch-file replace reference

首先发布在这里。

我正在尝试使用其他文本文件中的字符串将字符串更新(或添加)到纯文本文件。

示例:

File1.txt (参考文件)

<add key="1" value="False" />
<add key="2" value="C:\Temp" />
<add key="3" value="True" />
<add key="4" value="True" />
<add key="5" value="False" />
<add key="6" value="False" />
<add key="7" value="False" />
<add key="8" value="False" />
<add key="9" value="False" />
<add key="10" value="newkey" />
<add key="11" value="False" />
<add key="12" value="127.0.0.1" />
<add key="13" value="True" />
<add key="14" value="True" />
<add key="15" value="False" />
<add key="16" value="False" />
<add key="17" value="False" />
<add key="18" value="True" />
<add key="19" value="True" />
<add key="20" value="True" />
<add key="21" value="True" />
<add key="22" value="True" />

File2.txt (目标文件)

  <150 strings>
  </150 strings>

  <appSettings>
    <add key="1" value="False" />
    <add key="2" value="False" />
    <add key="3" value="False" />
    <add key="4" value="False" />
    <add key="5" value="False" />
    <add key="6" value="False" />
    <add key="7" value="False" />
    <add key="8" value="False" />
    <add key="9" value="False" />
    <add key="10" value="False" />
    <add key="11" value="False" />
    <add key="12" value="False" />
    <add key="13" value="False" />
    <add key="14" value="False" />
    <add key="15" value="False" />
    <add key="16" value="False" />
    <add key="17" value="False" />
    <add key="18" value="False" />
    <add key="19" value="False" />
    <add key="20" value="False" />
    <add key="21" value="False" />
    <add key="22" value="False" />
  </appSettings>
    <startup>
        <supportedRuntime/>
    </startup>
</configuration>

要求:

  1. 如果file2.txt已包含一个或所有密钥(即1到22),我想用file1.txt的密钥替换密钥。

  2. 如果file2.txt缺少file1.txt中存在的任何键,则需要添加它们。只要它们出现在<AppSettings>内,订单就无所谓了。

  3. 如果file2.txt包含file1.txt中不存在的键,则应将它们单独保留。

  4. <AppSettings>以外的任何内容都应保持不变。

  5. 在简要测试了Dbenham的最后一个脚本之后,看起来它完成了所有内容,但是上面和下面的行被移动了(我的错误是没有提供完整的示例)。

    以下是Dbenham剧本的当前输出:

      <150 strings>
      </150 strings>
    
      <appSettings>
      </appSettings>
        <startup>
            <supportedRuntime/>
        </startup>
    </configuration>
        <add key="1" value="False" />
        <add key="2" value="C:\Temp" />
        <add key="3" value="True" />
        <add key="4" value="True" />
        <add key="5" value="False" />
        <add key="6" value="False" />
        <add key="7" value="False" />
        <add key="8" value="False" />
        <add key="9" value="False" />
        <add key="10" value="newkey" />
        <add key="11" value="False" />
        <add key="12" value="127.0.0.1" />
        <add key="13" value="True" />
        <add key="14" value="True" />
        <add key="15" value="False" />
        <add key="16" value="False" />
        <add key="17" value="False" />
        <add key="18" value="True" />
        <add key="19" value="True" />
        <add key="20" value="True" />
        <add key="21" value="True" />
        <add key="22" value="True" />
    

2 个答案:

答案 0 :(得分:1)

@ECHO OFF
SETLOCAL
:: remove variables starting $ or #
For %%b IN ($ #) DO FOR  /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="

FOR /f "delims=" %%a IN (reference.txt) DO FOR /f "tokens=3delims== " %%h IN ("%%a") DO (
 SET "$%%~h=%%a"
)
FOR /f "delims=" %%a IN (target.txt) DO FOR /f "tokens=3delims== " %%h IN ("%%a") DO (
 SET "#%%~h=%%a"
)
(
 FOR  /F "tokens=1*delims=$=" %%c In ('set $ 2^>Nul') DO (
  ECHO(%%d
  SET "#%%c="
 )
 FOR  /F "tokens=1*delims==" %%c In ('set # 2^>Nul') DO (
  ECHO(%%d
 )
)>newfile.txt

GOTO :EOF

您的源数据具有“智能引号” - 我假设您实际使用了引号。

Essentailly,将$keyname =行设置为引用; #keyname =来自目标的行

然后输出所有$keyname并清除具有相同键名的任何#keyname

最后,输出所有剩余的#keyname s

结果显示在newfile.txt

答案 1 :(得分:0)

以下是基于更新问题的新答案

你真的应该使用一种用于编辑XML的工具。有许多方法可以以仍然有效的方式修改配置文件(file2.txt),但这会破坏任何纯批处理解决方案。但是,假设布局没有改变你所显示的......

如果你需要做的就是用file1.txt的内容替换file2.txt中的appSettings,那么:

@echo off
setlocal enableDelayedExpansion
set "replace="
>file2.txt.new (
  for /f "delims=" %%A in (file2.txt) do (
    set "ln=%%A"
    if "!ln:</appSettings>=!" neq "!ln!" (
      type file1.txt
      set "replace="
    )
    if not defined replace echo(!ln!
    if "!ln:<appSettings>=!" neq "!ln!" set replace=1
  )
)
move /y file2.txt.new file2.txt >nul

上面的保留file2.txt中找不到的任何在file1.txt中不存在的密钥。

如果你需要保存file2.txt中不存在于file1.txt中的密钥,那么修改Magoo的答案可能是最简单的解决方案:

@echo off
setlocal enableDelayedExpansion

for /f "delims==" %%A in ('set $ 2^>nul') do set "%%A="
set "replace="
>file2.txt.new (
  for /f "delims=" %%A in (file2.txt) do (
    set "ln=%%A"
    if not defined replace (
      echo(!ln!
      if "!ln:<appSettings>=!" neq "!ln!" set replace=1
    ) else if "!ln:</appSettings>=!" equ "!ln!" (
      for /f tokens^=2^ delims^=^" %%K in ("%%A") do set "$%%K=%%A"
    ) else (
      for /f "delims=" %%B in (file1.txt) do for /f tokens^=2^ delims^=^" %%K in ("%%B") do set "$%%K=%%B"
      for /f "tokens=1* delims==" %%B in ('set $') do echo(%%C
      echo(!ln!
      set "replace="
    )
  )
)
move /y file2.txt.new file2.txt >nul

上述两种解决方案都会破坏包含!的内容。如果需要支持!,则可以进行更改。解决方案还假设密钥不区分大小写。

此外,两个解决方案都将从file2.txt中删除空行。但这与XML文档无关。可以添加一些额外的代码来保留空行。

<强> 更新

以下是第二个解决方案的修改版本,该内容在内容中保留!个字符:

@echo off
setlocal disableDelayedExpansion

for /f "delims==" %%A in ('set $ 2^>nul') do set "%%A="
set "replace="
set "endReplace="
>file2.txt.new (
  for /f "delims=" %%A in (file2.txt) do (
    set "ln=%%A"
    if not defined replace (
      echo(%%A
      setlocal enableDelayedExpansion
      if "!ln:<appSettings>=!" neq "!ln!" (
        endlocal
        set replace=1
      ) else endlocal
    ) else (
      setlocal enableDelayedExpansion
      if "!ln:</appSettings>=!" equ "!ln!" (
        endlocal
        for /f tokens^=2^ delims^=^" %%K in ("%%A") do set "$%%K=%%A"
      ) else (
        endlocal
        for /f "delims=" %%B in (file1.txt) do for /f tokens^=2^ delims^=^" %%K in ("%%B") do set "$%%K=%%B"
        for /f "tokens=1* delims==" %%B in ('set $') do echo(%%C
        echo(%%A
        set "replace="
      )
    )
  )
)
move /y file2.txt.new file2.txt >nul

以下是基于原始问题中的这些file1.txt和file2.txt规范的原始答案:

File1.txt(参考文件)

<add key="abc" value="123" />
<add key="def" value="456" />
<add key="ghi" value="789" />

File2.txt(目标文件)

<add key="def" value="blank" />
<add key="ghi" value="blank" />

我假设您文件中的所有行都与您显示的模板匹配(除了使用普通的双引号而不是智能引号,正如Magoo指出的那样)。我还假设最终输出中的行顺序无关紧要,并且键不区分大小写。

假设密钥不包含空格。标签或反斜杠,然后:

@echo off
>file1.txt.screen (for /f "tokens=2" %%A in (file1.txt) do echo( %%A )
>file2.txt.new (
  findstr /livg:file1.txt.screen file2.txt
  type file1.txt
)
del file1.txt.screen
move /y file2.txt.new file2.txt >nul

如果键可能包含空格或制表符,但不包含反斜杠,则:

@echo off
>file1.txt.screen (for /f tokens^=2^ delims^=^" %%A in (file1.txt) do echo( key="%%A" )
>file2.txt.new (
  findstr /livg:file1.txt.screen file2.txt
  type file1.txt
)
del file1.txt.screen
move /y file2.txt.new file2.txt >nul

如果键可能包含空格或制表符或反斜杠,则:

@echo off
setlocal disableDelayedExpansion
>file1.txt.screen (
  for /f tokens^=2^ delims^=^" %%A in (file1.txt) do (
    set "key=%%A"
    setlocal enableDelayedExpansion
    (echo( key="!key:\=\\!" )
    endlocal
  )
)
>file2.txt.new (
  findstr /livg:file1.txt.screen file2.txt
  type file1.txt
)
del file1.txt.screen
move /y file2.txt.new file2.txt >nul

由于此FINDSTR错误,以上所有解决方案在查找密钥时都必须执行不区分大小写的搜索:Why doesn't this FINDSTR example with multiple literal search strings find a match?

<强>更新

以下是一个不区分大小写的解决方案,它消除了所有限制。

@echo off
setlocal disableDelayedExpansion
for /f tokens^=2^ delims^=^" %%A in (file1.txt) do (
  set "search= key="%%A" "
  setlocal enableDelayedExpansion
  (echo !search:\=\\!) >file2.txt.screen
  findstr /vlg:file2.txt.screen file2.txt >file2.txt.new
  move /y file2.txt.new file2.txt >nul
  endlocal
)
type file1.txt >>file2.txt
del file2.txt.screen