批量替换前2个字符

时间:2015-01-04 01:07:46

标签: 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; 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

谢谢!

4 个答案:

答案 0 :(得分:0)

好的我不知道如何检查它是以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

答案 1 :(得分:0)

您的回答并不符合以&#34;开头的行?需求。听起来像sed真的是这项工作的最佳工具。您可以获取GnuWin32 sed.exe并使用它来执行替​​换。顺便说一下,你的问题中的shell脚本可以通过允许sed内联读取和修改你的文件来缩短为单行:

sed -i -r -e '/^CLM/! s/^CL/CYLK/ig' -e 's/^CM/CLMR/ig' -e 's/^MD/MADX/ig' *.db

(如果您想在Windows中使用该行,请将单引号替换为double,以防止cmd将克拉解释为转义字符。)

如果您不想使用GnuWin32 sed,那么意识到Windows批处理中的正则表达式支持相当薄弱。有findstr,但它只支持最基本的正则表达式匹配,并且不进行替换。 (它就像一个非常弱的grep。)

如果你想要一个解决方案,你可以坚持使用.bat文件并运行它,那么我建议使用批处理/ JScript混合脚本,如下所示:

@if (@a==@b) @end /* begin JScript hybrid multiline comment

:: batch portion

@echo off
setlocal

for %%I in (*.db) do (
    cscript /nologo /e:JScript "%~f0" "%%~I"
)

goto :EOF

:: end batch / begin 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);

while (!reader.AtEndOfStream) {
    var line = reader.ReadLine();
    writer.WriteLine(line.replace(
        /^(md|cl|cm)(?!mx|mr)/ig,
        function(match, $1) {
            return {
                md: 'MADR',
                cl: 'CYLR',
                cm: 'CLMR'
            }[$1.toLowerCase()];
        }       // end function
    ));         // end replace() and WriteLine()
}               // end while

reader.Close();
writer.Close();

// uncomment if you don't wish to keep backup as .old
// fso.DeleteFile(oldFile);

如果要替换的字符串总是两个字母后跟数字,那么我建议用/^(md|cl|cm)(?=\d)/ig替换上面的正则表达式,以期望(但不包括)一个数字作为该行的第3个字符

你对JavaScript有多好?如果您对JavaScript感到满意,那么您(希望)会发现JScript易于遵循和维护。

答案 2 :(得分:0)

如果您可以一次完成所有替换,这是一个微不足道的问题。使用JREPL.BAT轻松完成 - 一种混合JScript /批处理实用程序,可执行正则表达式搜索并替换文本数据。 JREPL.BAT是纯脚本,可​​以在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

答案 3 :(得分:0)

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

@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