Batch file 批量替换前2个字符

Batch file 批量替换前2个字符,batch-file,batch-rename,Batch File,Batch Rename,我有一个文件的例子 CM2345 CLMX2345 CLMR5254 CYLR5121 CL2135 MADX5321 MD2145 MADR1234 CYLX1234 我需要做的是替换文件中以开头的所有行 md -> MADR cl -> CYLR cm -> CLMR 更换cl时会出现问题,因为clmx和clmr也从cl开始 这就是我在linux中所做的,现在我需要在windows批处理中使用它 for file in *.db; do while read p;

我有一个文件的例子

CM2345
CLMX2345
CLMR5254
CYLR5121
CL2135
MADX5321
MD2145
MADR1234
CYLX1234
我需要做的是替换文件中以开头的所有行

md -> MADR
cl -> CYLR
cm -> CLMR 
更换cl时会出现问题,因为clmx和clmr也从cl开始

这就是我在linux中所做的,现在我需要在windows批处理中使用它

for file in *.db; do

while read p; do

if  [[ "$p" == CL* ]] && [[ "$p" != CLM* ]] ;
then
r=$(echo $p | sed 's/..//')
echo $r > c.l

while read line
do
echo "CYLR$line" >> $file
done <c.l


fi

done <"$file"
wait

done
用于*.db中的文件;做
读p;做
如果[[“$p”==CL*]&&[“$p”!=CLM*];
然后
r=$(echo$p | sed's/./)
echo$r>c.l
读行时
做
回显“CYLR$line”>>$file

完成好的,我不确定如何检查它是否以clmx或clmr开始,并且不替换这些线路的cl,实际上我没有时间做这件事。我所做的是一个技巧,首先替换所有条目,然后修复错误的条目

(Get-Content .\t.txt) | ForEach-Object { $_ -replace "cl", "cylr" } | Set-Content .\t.txt
(Get-Content .\t.txt) | ForEach-Object { $_ -replace "md", "madr" } | Set-Content .\t.txt
(Get-Content .\t.txt) | ForEach-Object { $_ -replace "cm", "clmr" } | Set-Content .\t.txt
(Get-Content .\t.txt) | ForEach-Object { $_ -replace "cylrMX", "clmx" } | Set-Content .\t.txt
(Get-Content .\t.txt) | ForEach-Object { $_ -replace "cylrMr", "clmr" } | Set-Content .\t.txt

您的答案不符合“以行开头”的要求。听起来sed确实是这项工作的最佳工具。您可以获取并使用它来执行替换。顺便说一下,通过允许
sed
以如下方式内联读取和修改文件,您问题中的shell脚本可以缩短为一行:

sed -i -r -e '/^CLM/! s/^CL/CYLK/ig' -e 's/^CM/CLMR/ig' -e 's/^MD/MADX/ig' *.db
(如果要在Windows中使用该行,请将单引号替换为双引号,以防止
cmd
将克拉解释为转义字符。)

如果您不想使用GnuWin32
sed
,那么请意识到Windows批处理中对regexp的支持非常弱。有
findstr
,但它只支持最基本的regexp匹配,不进行替换。(它就像一个非常弱的
grep

如果您想要一个解决方案,可以插入
.bat
文件并运行它,然后我建议使用batch/JScript混合脚本,如下所示:

sed -i -r -e '/^CLM/! s/^CL/CYLK/ig' -e 's/^CM/CLMR/ig' -e 's/^MD/MADX/ig' *.db
@if(@a==@b)@end/*begin JScript混合多行注释
::批量部分
@回音
setlocal
对于(*.db)中的%%I,请执行以下操作(
cscript/nologo/e:JScript“%~f0”“%%~I”
)
后藤:EOF
::结束批处理/开始JScript*/
var fso=new ActiveXObject('scripting.filesystemobject'),
forReading=1,
dbFile=WSH.Arguments(0),
oldFile=dbFile.replace(/\.\w+$/,'.old');
fso.MoveFile(dbFile,oldFile);
var reader=fso.OpenTextFile(oldFile,forReading),
writer=fso.CreateTextFile(dbFile);
而(!reader.AtEndOfStream){
var line=reader.ReadLine();
writer.WriteLine(第行)替换(
/^(md | cl | cm)(?!mx | mr)/ig,
功能(匹配$1){
返回{
医学博士:“MADR”,
cl:‘赛尔’,
cm:“CLMR”
}[$1.toLowerCase()];
}//结束函数
));//end replace()和WriteLine()
}//结束时
reader.Close();
writer.Close();
//如果不希望将备份保留为.old,请取消注释
//fso.DeleteFile(旧文件);
如果要替换的字符串总是两个字母字符后跟数字,那么我建议将上面的regexp替换为
/^(md | cl | cm)(?=\d)/ig
,以查找(但不包括)一个数字作为行的第三个字符


你的JavaScript有多好?如果您熟悉JavaScript,您(希望)会发现JScript很容易按照需要进行操作和维护。

如果您可以一次完成所有替换,那么这是一个很小的问题。使用一个混合JScript/批处理实用程序,可以对文本数据执行正则表达式搜索和替换。是纯脚本,从XP开始在任何Windows计算机上本机运行

我使用
/T
选项将一系列搜索词转换为一系列替换词。
/I
选项忽略大小写,
/B
选项强制每个术语只匹配行的开头(比在每个术语中包含
^
更容易)。
/F
选项指定源文件,带有
-
值的
/O
选项导致输出替换原始文件

jrepl "MD CL CM" "MADR CYLR CLMR" /i /t " " /b /f test.txt /o -
如果在批处理脚本中使用,则必须使用CALL,因为JREPL也是批处理脚本

更新

如果行已经以一个目标字符串开头,则不应更改,则只需进行较小的更改:

jrepl "MD CL(?!MR) CM" "MADR CYLR CLMR" /i /t " " /b /f test.txt

这是一个纯粹的批处理文件程序,可以解决您所说的问题:

@echo off
setlocal EnableDelayedExpansion

rem Define the set of replacements:
for %%a in ("md=MADR" "cl=CYLR" "cm=CLMR") do for /F "tokens=1,2 delims==" %%b in (%%a) do set "replace[%%b]=%%c"

rem Define the values to preserve:
for %%a in (CLMX CLMR) do set preserve[%%a]=1

(for /F "delims=" %%a in (input.txt) do (
   set "line=%%a"
   for /F "tokens=1,2" %%b in ("!line:~0,4! !line:~0,2!") do (
      if not defined preserve[%%b] if defined replace[%%c] set "line=!replace[%%c]!!line:~2!"
   )
   echo !line!
)) > output.txt
输出示例:

CLMR2345
CLMX2345
CLMR5254
CYLR5121
CYLR2135
MADX5321
MADR2145
MADR1234
CYLX1234

有一个工具叫做“代码> SED AWK
,两者都可以做你想做的事情。同时,考虑一下你已经在做什么。我需要在Windows批量中运行这个工具。在linux中,我使用sed,并将新条目附加到文件的末尾。您可以使用MSYS在Windows中使用相同的linux命令。或者,如果您需要大量的批处理脚本,也可以在Windows中使用Perl或Python。嗯,有趣的是,我会尝试一下。但现在我需要批处理版本,因为此代码只是更大批处理脚本的一小部分,可以
jrepl.bat
排除替换
CLMX
/
CLMR
?根据主要问题中最上面的代码块,示例文件可能已经包含这些字符串,并且它们不需要更改。也许可以在您的解决方案中添加
cylrmx
cylrmr
的替换项,以消除错误匹配。@rojo-没问题。我对这个问题有不同的解释。我认为OP在分阶段执行搜索/替换时遇到了问题,因为其中一个目标字符串匹配了不同的搜索字符串,因此同一行可以修改两次。我最初的回答避免了这个问题。我添加了第二个解决方案,如果一行已经匹配其中一个目标字符串,则该解决方案不会更改该行。