我已经在网上搜索,但我找不到任何有用的文章。
这是我的情景:
例如,我有一个包含以下内容的文件:
AAAA 1111
BBBB 2222
CCCC 3333
假设1111,2222和3333位于20-23位置。我想要一个被调用的文件,用于确定行模式,起始位置,结束位置和用作替换的字符串。
示例文件名是replace.txt,其中包含以下内容:
BBBB 20 23 7777
现在,该文件将由执行此步骤的批处理文件调用:
我已经有了这个代码,可以在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
答案 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所述的修改。