首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Windows批处理文件以读取文件并替换字符串。

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

Stack Overflow用户
提问于 2016-09-12 07:20:23
回答 3查看 223关注 0票数 0

以下文件包含3份定购单。每个采购订单的第一行以一个常量记录标识符(我用粗体的字母)开头:

850 00000000000

我需要在每个PO中搜索字符串"MC66F“(它是斜体和粗体)。如果找到了字符串,那么我需要替换客户ID。然而,客户ID "ABC00“在所有的采购订单中。问题是,我只需要在包含字符串"MC66F“和"ABC04”的采购订单中更新客户ID。

850 00000000000123ABC 45 PO ABC00 79 79 1 000056

850 BEG002000009 22123ABC 45 20160909

850 CUR004000009欧元

850 REF00400000CR MC66F

850 DTM0170000013720160909

850 DTM0170000063 20160915

850 DTM0170000064 20160909

850 N1 0470000BY 5450534000031

850 N1 04700000SU 0728658000004

850 N1 04700000 N1 5450534002370

850 N1 04700000IV 5450534005821

850 PO1083000001 00000000000002EA200000000000009118 SAB00D9KR6T6

850 PO1083000002 00000000000012EA2000000000015294 SAB0058FAEAS

850 00000000000456ABC 45 PO ABC00 18132 18132 1 000056

850 BEG002000009 22456ABC 45 20160909

850 CUR004000009欧元

850 DTM0170000013720160909

850 DTM0170000063 20160914

850 DTM0170000064 20160909

850 N1 0470000BY 5450534000017

850 N1 04700000SU 608030938

850 N1 04700000 N1 0534002349

850 N1 04700000IV 5450534005838

850 PO1083000001 000000000000001EA2000000000010518 SAB00MYD9UP2

850 00000000000789ABC 45 PO ABC00 18133 18133 1 000056

850 BEG002000009 22789ABC 45 20160909

850 CUR004000009欧元

850 DTM0170000013720160909

850 DTM0170000063 20160914

850 DTM0170000064 20160909

850 N1 0470000BY 5450534000017

850 N1 04700000SU 608030938

850 N1 04700000 N1 0534002332

850 N1 04700000IV 5450534005838

850 PO1083000001 000000000000002EA2000000000010518 SAB00MYD9UP2

根据研究(以及我如何在UNIX中这样做),我尝试过的一些事情是将行存储在数组中,然后在数组中执行IF条件搜索字符串。我所能做的就是得到数组,但不知道如何利用IF条件。

代码语言:javascript
复制
    @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%

任何帮助都将不胜感激!

编辑:

代码语言:javascript
复制
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

)

我试图在文件中生成一个随机数,因为我认为它只是在用每次新的迭代覆盖文件。但这不管用。似乎它正在输出一个额外的“85000000000000”部分在下一个PO开始。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-09-12 15:03:49

代码语言:javascript
复制
@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

为了使代码更清晰,所有工作参数都是按字面顺序编写的,但您可以在变量或参数中指定它们的值。例如,您可以使用以下行启动代码:

代码语言:javascript
复制
set "search=MC66F"
set "old=ABC00"
set "new=ABC04"

..。然后调整代码中相应的行;例如:

代码语言:javascript
复制
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%!"
)
票数 0
EN

Stack Overflow用户

发布于 2016-09-12 11:18:16

我终于成功了。

步骤:

  • 读取输入文件内容并将其存储为环境变量(就像您所做的那样)。每个变量一行。不同之处在于,它使用了一些额外的逻辑:它不把文件视为行序列,而是将文件视为顺序序列,每个顺序都是记录序列(记录就是一行)。因此,(_ARRAY) env var是二维的(基于索引的):
代码语言:javascript
复制
- 1st index is the order
- 2nd index is the record (line) index inside the order

_OLENGTHS变量包含每个顺序的最后一个索引(长度- 1) (在本例中是12、10、10 ),它将在下一阶段使用。

  • 处理先前创建的env。它将每个订单头(第二个索引)保存到另一个变量中,以便稍后修改。然后,它遍历该订单的其余记录,搜索客户。如果它找到了它,它就会在标题中替换它。对于字符串/模式匹配,我使用了找到/?。 注意:我不得不使用标签,因为有些嵌套变量展开;这是我唯一能做到的方法。
  • 创建输出文件并将修改后的env内容转储到其中。

备注:

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

下面是代码:

代码语言:javascript
复制
@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

运行它之后,输出文件看起来像输入文件,除了第一行,它变成:

850 000000000000000123ABC 45 PO ABC04 79 1 000056

@EDIT0 0:我没有仔细阅读需求,而是用要搜索(MC66F)的字符串替换了客户(ABC00),而不是新客户(ABC04)。修正了。

票数 0
EN

Stack Overflow用户

发布于 2016-09-12 09:33:46

试试像这样的东西

代码语言:javascript
复制
powershell -command "(gc -Delimiter %delim% %file%)
     -replace %regex0%, %replace0% 
     .....
     -replace %regexn%, %replacen%
     -join %delim% | Set-Content %newfile%"

*换行符只供展示

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39445176

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档