как искать и заменять только точный регистр строк в файле

У меня есть скрипт «поиск и замена в файле», который работает, но не так, как я ожидаю. У него 2 проблемы:

  • он заменяет oldtext на newtext без regadd, если старый текст имеет больше строк после него: я хочу избежать этой ситуации!

я вызываю этот скрипт из пакетного файла, который содержит:

cscript replace.vbs файл.txt привет мир

предполагая, что file.txt содержит:

house
abc.hellowide.use
abc.hello.use
hello
hellonurse

Я хочу, чтобы скрипт изменил файл на это:

house
abc.hellowide.use
abc.world.use
wolrd
hellonurse

на данный момент скрипт приводит к нежелательным изменениям, например:

house
abc.worldwide.use
abc.world.use
wolrd
worldnurse

я хочу, чтобы был заменен только точный старый текст.

  • как я могу заставить сценарий рекурсивно использовать подпапки в корневом каталоге, из которого запускается сценарий?

вот мой скрипт до сих пор:

Const ForReading = 1
Const ForWriting = 2

strFileName = Wscript.Arguments(0)
strOldText = Wscript.Arguments(1)
strNewText = Wscript.Arguments(2)

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
strText = objFile.ReadAll
objFile.Close

strNewText = Replace(strText, strOldText, strNewText,1,1000,1)

Set objFile = objFSO.OpenTextFile(strFileName, ForWriting)
objFile.WriteLine strNewText
objFile.Close

person terminetorx    schedule 28.11.2012    source источник


Ответы (2)


Вы можете использовать регулярное выражение для замены «привет» на «мир», только если «привет» — это одно слово. Регулярное выражение для этого: \bhello\b. Он будет соответствовать hello и abc.hello.use, но не hellonurse и abc.hellowide.use.

Это может быть ваш сценарий:

Const ForReading = 1
Const ForWriting = 2

Dim re
Set re = new regexp

strFileName = Wscript.Arguments(0)
strOldText = Wscript.Arguments(1)
strNewText = Wscript.Arguments(2)

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
strText = objFile.ReadAll
objFile.Close

re.Pattern = "\b" + strOldText + "\b"
re.Global = True
re.Multiline = True

strNewText = re.Replace(strText, strNewText)

Set objFile = objFSO.OpenTextFile(strFileName, ForWriting)
objFile.WriteLine strNewText
objFile.Close

тогда вы можете назвать это так, чтобы заменить все файлы *.txt в текущей папке и подпапках:

for /r %a in (*.txt) do @cscript replace.vbs "%a" hello world

(есть еще что поправить, например в Аргументы(1) или Аргументы(2) содержат спецсимволы)

person fthiella    schedule 28.11.2012
comment
Еще кое-что. Как я могу заставить сценарий проникать во все файлы в sudirectories в корневом каталоге? (место, где я запускаю сценарий). эта способность имеет решающее значение для выполнения моей работы. - person terminetorx; 06.12.2012
comment
@terminetorx вы пытались запустить скрипт с помощью команды for выше? он должен делать то, что вам нужно... но если есть какие-либо проблемы, дайте мне знать - person fthiella; 06.12.2012

Строка (или токен, или аргумент) — это слова, разделенные пробелом или двойными кавычками, а не точками. Тогда abc.hello.use — это не 3 слова, а полное слово, поэтому его трудно выполнить так, как вы хотите.

Попробуйте это, но это не работает для .word. :

@echo off

:: By Elektro H@cker

Set "FILE=%~1"
Set "WORD_BEFORE=%~2"
Set "WORD_AFTER=%~3"

For /F "Tokens=*" %%# in ('Type "%FILE%"') do (
    Call :Replacer %%# 
    Call Set "Final_Line=%%FINAL_LINE:%FILE% %WORD_AFTER% %WORD_AFTER% =%%"
    call Echo %%FINAL_LINE:~1%%>>".\Output.txt"
    Call Set "Final_Line="
)

:Replacer
For %%@ in (%*) do ( 
    IF "%%@" EQU "%WORD_BEFORE%" (
        Call Set "Final_Line=%%FINAL_LINE%% %WORD_AFTER%"
    ) ELSE (
        Call Set "Final_Line=%%FINAL_LINE%% %%@"
    )
)
GOTO:EOF

Для любых других текстовых манипуляций вы можете использовать мою подпрограмму Batch:

@Echo OFF

:: TEXT MANIPULATOR ROUTINE v0.1
:: by Elektro H@cker

REM USE:
::TEXTMAN [ACTION] [IN LINE (Optional)] [FILE] [TEXT (Optional)]


REM ACTIONS:
REM 
REM  AL  = ADD_LEFT           * Add text to the beginning of a line
REM  AR  = ADD_RIGHT          * Add text to the end of a line
REM  E   = ERASE              * Delete a line
REM  I   = INSERT             * Add a empty line (Or a line with text)
REM  RL  = REPLACE_LINE       * Replace a line
REM  RS  = REPLACE_STRING     * Replace words of a line
REM  RSA = REPLACE_STRING_ALL * Replace words of all line
REM  C+  = CHARACTER_PLUS     * Delete the first "X" characters in all lines
REM  C-  = CHARACTER_LESS     * Delete the last  "X" characters in all lines
REM  L+  = LINE_PLUS          * Cut the first "X" lines
REM  L-  = LINE_LESS          * Cut the last  "X" lines


REM EXAMPLES:

:: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: ::
::
:: Deletes the line 3
:: Call :TEXTMAN E 3 "Test.txt"
::
:: Add a phrase to the beginning of line 3
:: Call :TEXTMAN AL 3 "Test.txt" "Elektro H@cker"
::
:: Add a phrase to the end of line 3
:: Call :TEXTMAN AR 3 "Test.txt" "Elektro H@cker"
::
:: Add a empty line at line 3
:: Call :TEXTMAN I 3 "Test.txt"
:: 
:: Add a line with a word at line 3
:: Call :TEXTMAN I 3 "Test.txt" "Elektro H@cker"
::
:: Replaces the line 3 with "Elektro H@cker"
:: Call :TEXTMAN RL 3 "Test.txt" "Elektro H@cker"
::
:: Replaces the words "Elektro" to "H@cker" in line 3
:: Call :TEXTMAN RS 3 "Test.txt" "Elektro" "H@cker"
::
:: Replaces the words "Elektro" to "H@cker" in all lines
:: Call :TEXTMAN RSA "Test.txt" "Elektro" "H@cker"
::
:: Deletes the first 3 characters in all lines
:: Call :TEXTMAN C+ 3 "Test.txt"
::
:: Deletes the last 3 characters in all lines
:: Call :TEXTMAN C- 3 "Test.txt"
::
:: Deletes the first 3 lines
:: Call :TEXTMAN L+ 3 "Test.txt"
::
:: Deletes the last 3 lines
:: Call :TEXTMAN L- 3 "Test.txt"
::
:: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: :: ::

:TEXTMAN
(SET /A "A=0", "LINE=0", "TOTAL_LINES=0")  &  (CALL :%~1 %* || (ECHO Parametro incorrecto & Exit /B 1)) & (GOTO:EOF)
:AL
(For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set /A "LINE+=1" && (CMD /C "IF NOT "%%LINE%%" EQU "%~2" (Echo %%@ >> "%~nx3.NEW") ELSE (Echo %~4%%@ >> "%~nx3.NEW")"))) && (CALL :RENAMER "%~3") & (GOTO:EOF)
:AR
(For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set /A "LINE+=1" && (CMD /C "IF NOT "%%LINE%%" EQU "%~2" (Echo %%@ >> "%~nx3.NEW") ELSE (Echo %%@%~4 >> "%~nx3.NEW")"))) && (CALL :RENAMER "%~3") & (GOTO:EOF)
:E
(For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set /A "LINE+=1" && (CMD /C "IF NOT "%%LINE%%" EQU "%~2" (Echo %%@ >> "%~nx3.NEW")"))) && (CALL :RENAMER "%~3") & (GOTO:EOF)
:I
(For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set /A "LINE+=1" && (CMD /C "IF     "%%LINE%%" EQU "%~2" (IF NOT "%~4" EQU "" (Echo %~4 >> "%~nx3.NEW") ELSE (Echo. >> "%~nx3.NEW"))" & Echo %%@ >> "%~nx3.NEW"))) && (CALL :RENAMER "%~3") & (GOTO:EOF)
:RL
(For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set /A "LINE+=1" && (CMD /C "IF NOT "%%LINE%%" EQU "%~2" (Echo %%@ >> "%~nx3.NEW") ELSE (Echo %~4 >> "%~nx3.NEW")"))) && (CALL :RENAMER "%~3") & (GOTO:EOF)
:RS
(For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set /A "LINE+=1" && (CMD /C "IF NOT "%%LINE%%" EQU "%~2" (Echo %%@ >> "%~nx3.NEW") ELSE (CALL SET "STRING=%%@" && CALL ECHO %%STRING:%~4=%~5%% >> "%~nx3.NEW")"))) && (CALL :RENAMER "%~3") & (GOTO:EOF)
:RSA
(For /F "usebackq tokens=*" %%@ in ("%~2") DO (CALL SET "STRING=%%@" && (CALL ECHO %%STRING:%~3=%~4%% >> "%~2.NEW"))) && (CALL :RENAMER "%~2") & (GOTO:EOF)
:C+
(For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set   "LINE=%%@" && (CALL ECHO %%LINE:~%~2%% >>    "%~nx3.NEW"))) && (CALL :RENAMER "%~3") & (GOTO:EOF)
:C-
(For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set   "LINE=%%@" && (CALL ECHO %%LINE:~0,-%~2%% >> "%~nx3.NEW"))) && (CALL :RENAMER "%~3") & (GOTO:EOF)
:L+
(Call SET /A "A=%~2-1") && (Call TYPE "%~3" | @MORE +%%A%% > "%~nx3.NEW") && (CALL :RENAMER "%~3") & (GOTO:EOF)
:L-
(FOR /F %%X IN ('TYPE "%~3"') DO (CALL SET /A "TOTAL_LINES+=1")) & (CALL SET /A "TOTAL_LINES-=%~2-1") & (For /F "usebackq tokens=*" %%@ in ("%~3") DO (Call Set /A "LINE+=1" & Call echo " %%LINE%%!!| FINDSTR " %%TOTAL_LINES%% " && CALL :RENAMER "%~3" && GOTO:EOF || (Echo %%@ >> "%~nx3.NEW")))
:RENAMER
(REN "%~1" "%~nx1.BAK") & (MOVE /Y "%~nx1.BAK" "%TEMP%\" >NUL) & (REN "%~nx1.NEW" "%~nx1") & (GOTO:EOF)
person ElektroStudios    schedule 28.11.2012