如何根据开始和结束位置查找和替换字符串

时间:2014-11-11 13:37:21

标签: regex windows batch-file text cmd

我已经在网上搜索,但我找不到任何有用的文章。

这是我的情景:

例如,我有一个包含以下内容的文件:

AAAA            1111
BBBB            2222
CCCC            3333

假设1111,2222和3333位于20-23位置。我想要一个被调用的文件,用于确定行模式,起始位置,结束位置和用作替换的字符串。

示例文件名是replace.txt,其中包含以下内容:

BBBB    20    23     7777

现在,该文件将由执行此步骤的批处理文件调用:

  1. 查找以BBBB开头的行,
  2. 用替换.txt文件中指示的7777替换位置20-23,即2222。
  3. 我已经有了这个代码,可以在replace.txt文件中找到的每个匹配项中进行迭代。

    for /f "tokens=1-4" %%s in (replace.txt) do (
        Type "C:\user\linefeed\%%a.in.tmp"  | C:\user\bat\repl.bat "\%%s" "%%t" X > "C:\user\linefeed\%%a.out.tmp"
        move /y "C:\user\linefeed\%%a.out.tmp" "C:\user\linefeed\%%a.in.tmp"
      )
      move "C:\user\linefeed\%%a.in.tmp" "C:\user\out\%%a"
    

    现在,我将如何实施上述方案?首先找到线条图案,开始和结束位置,在指示的开始和结束位置找到的任何字符串将被替换为replace.txt的标记4。

    预期输出必须是:

    AAAA            1111
    BBBB            7777
    CCCC            3333
    

4 个答案:

答案 0 :(得分:1)

当您使用repl.bat并使用JScript正则表达式时,请使用捕获组

搜索表达式:^(BBBB.{15}).{4}(.*)$

替换表达式:$17777$2

正则表达式是:从行的开头,找到四个B个字符后跟15个字符(任意字符)并将其捕获为第一个组(括号),然后再读取另外四个字符(非捕获),然后是所有角色,直到作为第二组捕获的线的末尾。

在替换表达式中,$1是第一对括号中表达式匹配的所有文本,$2是第二对括号中表达式匹配的文本。

已编辑以评论内容

file:data.txt

AAAA               1111
BBBB               2222
CCCC               3333

file:findnreplace.txt

^(BBBB.{15}).{4}(.*)$ $17777$2
CCCC XXXX
AAAA aaaa

file:test.cmd

@echo off
    setlocal enableextensions disabledelayedexpansion

    for %%a in (data*.txt) do (
        copy "%%a" "%%a.in.tmp"
        for /f "tokens=1,*" %%s in (FindNReplace.txt) do (
            Type "%%a.in.tmp"  | repl.bat "%%s" "%%t" X > "%%a.out.tmp"
            move /y "%%a.out.tmp" "%%a.in.tmp"
        )
        move "%%a.in.tmp" "%%a"
    )

结果:data.txt

aaaa               1111
BBBB               7777
XXXX               3333

答案 1 :(得分:0)

@ECHO OFF
SETLOCAL
(
 FOR /f "delims=" %%a IN (q26866198.txt) DO CALL :massage "%%a" "%~1" %2 %3 "%~4"
)>newfile.txt

TYPE newfile.txt

GOTO :EOF

:: If %1 begins %2 then replace columns %3 to %4 with %5

:massage
ECHO %~1|FINDSTR /b /L /c:"%~2" >NUL
IF ERRORLEVEL 1 ECHO(%~1&GOTO :EOF
SETLOCAL ENABLEDELAYEDEXPANSION 
SET "line=%~1"
SET /a endpoint=%3-1
ECHO(!line:~0,%endpoint%!%~5!line:~%4!
GOTO :eof

我使用了一个名为q26866198.txt的文件,其中包含我的测试数据。

制作newfile.txt

执行 thisbatch BBBB 20 23 7777

将cols 20..23替换为“7777”,以“BBBB”开头的行

它可能会像批处理中的大多数字符串操作例程一样有点脆弱 - 它根本就不是为工作而构建的。


此例程读取文件q26866198.txt,依次将每行应用于%%a并执行:massage过程。该过程的所有输出都在newfile.txt中累积。当然,文件名是名义上的。

:massge接受5个参数。 %1是原始文件的(引用)输入行。 %2是字符串匹配。 %3是要替换的起始列,%4是要替换的结束列。 %5是要插入的字符串,代替列%3 ..%4应该%2匹配%1的开头。

第一步是测试该行是否与字符串匹配,因此行本身(%1)不加引号并通过管道输出到findstr,输出为nul,因此测试是静默的。参数为/b(在行的开头)/L(文字匹配)和/c:"string"(此常量字符串,可能包含空格。%2被取消引用并使用作为这个字符串。

如果字符串不匹配,则errorlevel设置为1,因此原始字符串为echo ed,dequoted并且子例程退出。

否则,字符串匹配,因此我们设置本地环境并建立delayedexpansion模式以允许嵌套!var!%var%以利用cmd解析特性。

line设置为匹配从文件读取的原始字符串,并计算要再现的列数(比起始列少1)到endpoint

然后我们需要从endpoint输出第一个line字符,然后输出替换字符串(%5去引号),然后输出第%4列之后的剩余部分。由于cmd开始计算来自0的列,因此我们需要子串!line:~0,%endpoint%!和字符串%~5以及字符串!line:~%4连接在一起;利用cmd的解析方案,在延迟扩展模式%n%var%和!var!按此顺序进行评估和替换。

运行代码的问题可能是由于发布的样本数据具有从第17列开始的替换数据,而不是如上所述的20。

样本数据(略有修改)

AAAA               1111
BBBB               2222
BBBB              922220987
CCCC               3333

结果数据以 thisbatch BBBB 20 23 7777

执行
AAAA               1111
BBBB               7777
BBBB              977770987
CCCC               3333

答案 2 :(得分:0)

您要做的是使用以下正则表达式匹配固定数量的字符:

.{30}

以上正则表达式将匹配正好30个字符。因此,您在上面的示例中所做的是在模式之后匹配足够的字符以到达要替换的部分,匹配另一个字符数以匹配要替换的部分,最后替换最后一个匹配部分。

假设变量P,A,B和R分别是模式,起始位置,结束位置和替换。以下是使用JavaScript作为宿主语言通过正则表达式进行替换的方法:

"(?<=" + P + ".{" + (P.length - A) + "})(.{" + (B - A) + "})"

然后替换比赛。背后的正面外观(?&lt; =)用于仅匹配P之后的B-A字符。

答案 3 :(得分:0)

我认为您正在寻找的正则表达式是:

C:\user\bat\repl.bat "^%%s.*" "$0.substr(0,%%t)+'%%v'+$0.substr(%%u+1)" J

例如,使用先前的数据BBBB 20 23 7777,前一行变成了这一行:

C:\user\bat\repl.bat "^BBBB.*" "$0.substr(0,20)+'7777'+$0.substr(23+1)" J

那就是:寻找以“BBBB”开头的行,并用前20个字符替换整行,然后是“7777”,接着是从字符24开始的其余行。我不知道如果“位置20-23”是零或一个基础,但在这种情况下只需要进行微调。

但是,您必须使用REPL.BAT version 6.1才能使用新的J开关。

您也可以使用我的FindRepl.bat程序来实现此替换,但您必须插入at this post所述的修改。