Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows批处理文件以读取文件并替换字符串_Windows_Loops_Batch File_Replace_Find - Fatal编程技术网

Windows批处理文件以读取文件并替换字符串

Windows批处理文件以读取文件并替换字符串,windows,loops,batch-file,replace,find,Windows,Loops,Batch File,Replace,Find,下面的文件包含3个采购订单。每个采购订单的第一行以一个常量记录标识符开始,我用粗体字母表示: 850亿 我需要在每个订单中搜索字符串MC66F,它是斜体和粗体的。如果找到该字符串,则我需要替换客户ID。但是,所有采购订单中都有客户ID ABC00。问题是我只需要更新包含字符串MC66F和ABC04的采购订单中的客户ID 850 00000000000123ABC45采购订单ABC00 79 1 000056 850 BEG002000009 22123ABC45 20160909 850 CUR

下面的文件包含3个采购订单。每个采购订单的第一行以一个常量记录标识符开始,我用粗体字母表示:

850亿

我需要在每个订单中搜索字符串MC66F,它是斜体和粗体的。如果找到该字符串,则我需要替换客户ID。但是,所有采购订单中都有客户ID ABC00。问题是我只需要更新包含字符串MC66F和ABC04的采购订单中的客户ID

850 00000000000123ABC45采购订单ABC00 79 1 000056 850 BEG002000009 22123ABC45 20160909 850 CUR004000009欧元 850参考文献00400000Cr MC66F 850 DTM017000013720160909 850 DTM0170000063 20160915 850 DTM0170000064 20160909 850 N1 04700000乘5450534000031 850 N1 04700000SU 0728658000004 850 N1 04700000DP 5450534002370 850 N1 04700000IV 5450534005821 850 PO10830000100000000000002EA2000000000009118 SAB00D9KR6T6 850 PO1083000000000000000000 12EA2000000000000015294 SAB0058FAEAS 850 00000000000 456ABC45采购订单ABC00 18132 18132 1 000056 850 BEG002000009 22456ABC45 20160909 850 CUR004000009欧元 850 DTM017000013720160909 850 DTM017000063 20160914 850 DTM0170000064 20160909 850 N1 04700000乘5450534000017 850 N1 04700000SU 608030938 850 N1 04700000DP 0534002349 850 N1 04700000IV 5450534005838 850 PO1083000001 0000000000000001EA200000000000010518 SAB00MYD9UP2 850 00000000000 789ABC45采购订单ABC00 18133 18133 1 000056 850 BEG002000009 22789ABC45 20160909 850 CUR004000009欧元 850 DTM017000013720160909 850 DTM017000063 20160914 850 DTM0170000064 20160909 850 N1 04700000乘5450534000017 850 N1 04700000SU 608030938 850 N1 04700000DP 0534002332 850 N1 04700000IV 5450534005838 850 PO1083000001 0000000000000002EA2000000000010518 SAB00MYD9UP2

基于研究和在UNIX中的实现方法,我尝试过的一些方法是将行存储在数组中,然后执行IF条件搜索数组中的字符串。我所能做的就是获取数组,但却不知道如何利用IF条件

    @echo off &setlocal enabledelayedexpansion
    for /F "delims=" %%a in (%INPUTFILE%) do (
      set /A count+=1
      set "array[!count!]=%%a"
    )
    for /L %%i in (1,1,%count%) do echo !array[%%i]! >> %OUTPUTFILE%
任何帮助都将不胜感激

编辑:

for %%b in (inputfile.*) do (

rem Process all input lines and create output file

(
setlocal EnableDelayedExpansion

for /F "delims=" %%a in (%%~fb) do (
   set "line=%%a"
   rem If new order starts
   if "!line:~0,17!" equ "850   00000000000" (
      rem show the previous one
      if defined firstLine (
         echo !firstLine!
         type thisOrder.txt
         del thisOrder.txt
     )
      rem and start new order
      set "firstLine=%%a"
   ) else (
      rem If the string was found in this order
      if "!line:%search%=!" neq "%%a" (
         rem replace the customer ID in first line
         set "firstLine=!firstLine:%old%=%new%!"
   )    
      rem Save this line in this order
      echo %%a>> thisOrder.txt
   )

)
echo !firstLine!
type thisOrder.txt
del thisOrder.txt

) > output.%RANDOM%.txt

)

我试图在文件中生成一个随机数,因为我认为它只是在用每个新的迭代覆盖文件。但这不起作用。似乎它在下一个订单开始时输出了一个额外的8500000000000段。

试试这样的方法

powershell -command "(gc -Delimiter %delim% %file%)
     -replace %regex0%, %replace0% 
     .....
     -replace %regexn%, %replacen%
     -join %delim% | Set-Content %newfile%"

*换行符只是为了显示,我终于做到了

步骤:

读取输入文件内容并将其存储为环境变量,就像您所做的那样。每个变量一行。不同之处在于它使用了一些额外的逻辑:它不将文件视为一个行序列,而是将其视为一个顺序序列,每个顺序都是一个记录序列,一个记录就是一行。因此,_arrayenv var是基于0的二维索引:

第一个索引是顺序 第二个索引是订单内的记录行索引 在我们的例子中,_OLENGTHS变量包含每个12 10 10阶的最后一个索引长度-1,它将在下一阶段使用

处理以前创建的环境变量。它将每个订单头的第二个索引0保存到另一个var中,以便以后修改。然后它通过该顺序的其余部分进行迭代 记录,搜索客户。如果找到它,它将在标题中替换它。对于字符串/模式匹配,我使用了

注意:我不得不使用标签,因为一些嵌套变量会扩展;这是我能做到的唯一方法

创建输出文件并将修改后的env vars内容转储到其中

注:

代码可能效率很低。我没有花时间优化它。 它依赖于一个事实,即每个订单以850亿开始。 它还依赖于这样一个事实:客户记录具有以下格式:850 REF,后跟一系列数字和字母+小写,然后是空格,然后是客户名称。 它依赖于在订单记录中,需要更换的客户是第四个令牌。 代码如下:

@echo off
setlocal enabledelayedexpansion
set _INPUTFILE=in.txt
set _OUTPUTFILE=out.txt
set _OIDX=-1
set _RIDX=0
set _OLENGTHS=
set _RECORD=
set _HEADER=
set _IDMARK=850 00000000000
set _REFMARK=850 REF
set _CUSTOMER=MC66F
set _NEWCUSTOMER=ABC04

:: Read the inoput file contents and store it in env vars
for /f "tokens=*" %%f in (%_INPUTFILE%) do (
    echo %%f | findstr /b /c:"%_IDMARK%" 1>nul
    if !errorlevel! equ 0 (
        set /a _OIDX+=1
        if "!_RECORD!" neq "" (
            set _OLENGTHS=!_OLENGTHS! !_RIDX!
        ) else (
            set _RECORD=_
        )
        set /a _RIDX=0
    ) else (
        set /a _RIDX+=1
    )
    set _ARRAY[!_OIDX!][!_RIDX!]=%%f
)
set _OLENGTHS=%_OLENGTHS% %_RIDX%

:: Do some processing on the env vars
set /a _OIDX=-1
for %%f in (%_OLENGTHS%) do (
    set /a _OIDX+=1
    call :set_header_var !_OIDX!
    for /l %%g in (1,1,%%f) do (
        call :process_record !_OIDX! %%g
    )
)

:: Dump all the env vars contents into the output file
copy nul %_OUTPUTFILE%
set /a _OIDX=-1
for %%f in (%_OLENGTHS%) do (
    set /a _OIDX+=1
    call :set_header_var !_OIDX!
    for /l %%g in (0,1,%%f) do (
        call :dump_var !_OIDX! %%g
    )
)

goto :eof

:process_record
    echo !_ARRAY[%1][%2]! | findstr /r /c:"^%_REFMARK%[0-9A-Za-z]* %_CUSTOMER%" 1>nul
    if !errorlevel! equ 0 (
        call :alter_header %1
    )
    goto :eof

:set_header_var
    set _HEADER=!_ARRAY[%1][0]!
    goto :eof

:alter_header
    for /f "tokens=1,2,3,4,*" %%h in ('echo !_HEADER!') do (
        set _ARRAY[%1][0]=%%h %%i %%j %_NEWCUSTOMER% %%l
    )
    goto :eof

:dump_var
    echo !_ARRAY[%1][%2]!>>%_OUTPUTFILE%
    goto :eof
运行后,输出文件与输入文件类似,但第1行变为:

8500000000000123ABC45采购订单ABC04 79 79 1 000056

@EDIT0:我没有仔细阅读需求,我用字符串替换客户ABC00以搜索MC66F,而不是新客户ABC04。更正

@echo off
setlocal EnableDelayedExpansion

set "firstLine="
del thisOrder.txt 2>NUL

rem Process all input lines and create output file
(
for /F "delims=" %%a in (input.txt) do (
   set "line=%%a"
   rem If new order starts
   if "!line:~0,15!" equ "850 00000000000" (
      rem show the previous one
      if defined firstLine (
         echo !firstLine!
         type thisOrder.txt
         del thisOrder.txt
      )
      rem and start new order
      set "firstLine=%%a"
   ) else (
      rem If the search string was found in this order
      if "!line:MC66F=!" neq "%%a" (
         rem replace the customer ID in first line
         set "firstLine=!firstLine:ABC00=ABC04!"
      )
      rem Save this line in this order
      echo %%a>> thisOrder.txt
   )
)
echo !firstLine!
type thisOrder.txt
del thisOrder.txt
) > output.txt
为了使代码更清晰,所有工作参数都是逐字写入的,但是您可以在变量或参数中指定它们的值。例如,您可以使用以下行开始代码:

set "search=MC66F"
set "old=ABC00"
set "new=ABC04"
。。。然后调整代码中的对应行;例如:

rem If the search string was found in this order
if "!line:%search%=!" neq "%%a" (
   rem replace the customer ID in first line
   set "firstLine=!firstLine:%old%=%new%!"
)

将旧记录与新更新记录进行比较时,新第一行的输出在位置上处于关闭状态。旧:850 00000000000 123ABC45 PO ABC00 18132 18132 1 000056 00000 4010004010X X401401010010 PP新:850 00000000000 123ABC45 PO MC66F 79 1 000056 00000 4010004010X X4011010010我希望将其更改为到ABC04。搜索字符串为MC66F。用户@Aacini代码似乎如我所希望的那样工作。再次感谢您的投入!非常感谢。我认为我的原始文本的复制/粘贴在位置上有问题,因此我必须将~0,15更新为~0,18。我还使用了您关于在变量中指定值的附加注释,这非常有效!再次感谢大家!嗨,Aacini,我遇到了一个问题,使用此代码处理目录中的多个文件。我试着使用FOR循环,查看带有编辑的原始帖子,看看我拍摄的是什么。嗨@Aacini,你认为你能帮我吗?你忘了在每个文件的流程中包含这行集合firstLine=。您还必须在开始时将setlocal EnableDelayedExpansion行移到for外部。最后,如果您有多个名为inputfile的文件,其扩展名与inputfile不同。*通配符建议,我建议您在每个输出文件中使用相同的输入文件扩展名:>output%%~xbThank,再次@Aacini!