2015-01-04 2 views
0

Я имею этот пример файлаПакетная заменить первые 2 символа

CM2345 
CLMX2345 
CLMR5254 
CYLR5121 
CL2135 
MADX5321 
MD2145 
MADR1234 
CYLX1234 

Что мне нужно сделать, это заменить все строки в файле, начиная с

md -> MADR 
cl -> CYLR 
cm -> CLMR 

Проблема возникает, когда заменяя cl, так как clmx и clmr также начинаются с cl.

Это, как я сделал это в Linux, теперь мне это нужно в окнах партии

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 

Спасибо!

+0

Существует инструмент под названием 'sed', а другой -' awk', оба могут делать то, что вы хотите. – MondKin

+0

Также подумайте о том, что вы уже пытаетесь. – MondKin

+0

Ну, мне нужно запустить это в пакетном режиме Windows. в linux я сделал это с sed, и я добавляю новые записи в конец файла. –

ответ

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 
0

Вашего ответ не соответствует вашей «строке, начинающейся с» требованием. Похоже, sed действительно был бы лучшим инструментом для работы. Вы можете получить GnuWin32 sed.exe и использовать это для выполнения своих замен. Кстати, что сценарий оболочки в вашем вопросе может быть сокращен до одной строки, позволяя sed читать и изменять файлы встраивать как это:

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, является довольно слабой. Есть findstr, но он поддерживает только самое основное соответствие регулярному выражению и не выполняет замены. (Это похоже на очень слабый grep.)

Если вы хотите решение, которое вы можете придерживаться в .bat файл и запустить его, то я предлагаю пакетный/JScript гибридный сценарий, что-то вроде этого:

@if (@[email protected]) @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); 

Если строки, которые вы хотите заменить, всегда являются двумя альфа-символами, за которыми следуют цифры, тогда я предлагаю заменить regexp выше на /^(md|cl|cm)(?=\d)/ig, чтобы смотреть вперед (но не включать) число в качестве третьего символа строки.

Насколько вы владелец? Если вам нравится JavaScript, вы (надеюсь) найдете, что JScript легко отслеживать и поддерживать по мере необходимости.

0

Это тривиальная проблема, если вы можете делать все замены за один проход. Легко делается с помощью JREPL.BAT - гибридной утилиты JScript/пакетной обработки, которая выполняет поиск регулярных выражений и заменяет текстовые данные. JREPL.BAT - это чистый сценарий, который запускается изначально на любой машине Windows с XP.

Я использую опцию /T, чтобы перевести серию поисковых терминов в ряд условий замены. Опция /I игнорирует регистр, а опция /B заставляет каждый термин соответствовать началу строки (проще, чем включение ^ с каждым термином).Опция /F указывает исходный файл, а параметр /O с значением - заставляет исходный файл заменить исходный файл.

jrepl "MD CL CM" "MADR CYLR CLMR" /i /t " " /b /f test.txt /o - 

При использовании пакетного сценария, то вы должны использовать ВЫЗОВ поскольку JREPL также пакетный сценарий.

UPDATE

Если линии не должны быть изменены, если они уже начинают с одной из целевых строк, то лишь незначительные изменения необходимы:

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

Может ли 'jrepl.bat' исключить замену' CLMX'/'CLMR'? Согласно верхнему блоку кода в основном вопросе, файл примера может уже содержать эти строки, и их не нужно изменять. Возможно, добавьте замены для 'cylrmx' и' cylrmr' к вашему решению, чтобы утка ударила по ошибочным совпадениям. – rojo

+0

@rojo - проблем нет. У меня была другая интерпретация проблемы. Я думал, что у ОП возникали проблемы с поиском/заменой поэтапно, когда одна из целевых строк соответствовала другой строке поиска, так что одна и та же строка могла быть изменена дважды. Мой первоначальный ответ позволяет избежать этой проблемы. Я добавил второе решение, которое не меняет строку, если оно уже соответствует одной из целевых строк. – dbenham

0

Это чисто Batch файл программы, которые решают проблему, как вы заявил:

@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 
Смежные вопросы