Як можна знайти та замінити текст у файлі, використовуючи середовище командного рядка Windows?


492

Я пишу сценарій пакетного файлу, використовуючи середовище командного рядка Windows і хочу змінити кожне виникнення деякого тексту у файлі (наприклад, "FOO") іншим (наприклад, "BAR"). Який найпростіший спосіб це зробити? Будь-які вбудовані функції?



скористайтеся цим:echo(%text:%search%=%replace%%)
scientist_7

Відповіді:


308

Багато відповідей тут допомогло мені направити в правильному напрямку, проте жодна не підходила мені, тому я публікую своє рішення.

У мене є Windows 7, в якому вбудований PowerShell. Ось сценарій, який я використовував для пошуку / заміни всіх примірників тексту у файлі:

powershell -Command "(gc myFile.txt) -replace 'foo', 'bar' | Out-File -encoding ASCII myFile.txt"

Щоб пояснити це:

  • powershell запускає powershell.exe, який включений у Windows 7
  • -Command "... " - аргумент командного рядка для powershell.exe, що містить команду для запуску
  • (gc myFile.txt)читає вміст myFile.txt( gcкороткий для Get-Contentкоманди)
  • -replace 'foo', 'bar'просто запускає замінити команду , щоб замінити fooзbar
  • | Out-File myFile.txt передає вихід у файл myFile.txt
  • -encoding ASCII заважає переписувати вихідний файл в unicode, як вказують коментарі

Powershell.exe має бути частиною вашого твердження PATH, але якщо ні, ви можете додати його. Місце його розташування на моїй машиніC:\WINDOWS\system32\WindowsPowerShell\v1.0


71
Остерігайтеся, ця команда може також перекодувати файл у кодування Unicode. Ви можете вручну вказати кодування, додавши -encoding ASCIIабо UTF8або все , що необхідно. Також будьте обережні, якщо ви орієнтуєтесь на UTF8, він може ввести позначку порядку байтів на початку файлу, який не відображався в оригіналі.
Вік

78
@Wyck Мені знадобилося певний час, щоб зрозуміти, куди його поставити -encoding ASCII. Для кожного, хто цього потребує, це будеOut-File -encoding ASCII myFile.txt
rwilson04

15
Єдине, що мені довелося змінити - це використовувати Set-Content замість цього Out-File.
kurtzmarc

6
Це працює, але продуктивність жахлива навіть у короткому списку файлів.
jsuddsjr

23
Будьте уважні, що маркер заміни ("foo" в даному випадку) трактується як регулярний вираз. Якщо у вас є якісь спеціальні символи (у мене був []), вам потрібно додати їх \ (зворотна косої риски).
JW

183

Якщо ви користуєтеся версією Windows, яка підтримує .Net 2.0, я б замінив вашу оболонку. PowerShell дає вам повну потужність .Net з командного рядка. Вбудовано також багато командлетів. Наведений нижче приклад вирішить ваше запитання. Я використовую повні назви команд, є короткі псевдоніми, але це дає вам щось для Google.

(Get-Content test.txt) | ForEach-Object { $_ -replace "foo", "bar" } | Set-Content test2.txt

10
Я можу бачити, що PowerShell здатний цього досягти. Але як я можу зробити цей запуск з пакетного файлу (приклад: myProc.bat)?
Пабло Вентурино

3
@Pablo, використовуйте powershell.exe і загортайте команду ps в єдиний параметр
lubos hasko

56
-1 .. Впевнений, що відповідь прийнято, але це не відповідь на вказане питання.
baash05

28
Це не вдасться з помилкою при використанні файлу, якщо ви збережете його в одному файлі. Вам потрібно змінити команду повноважень на: (Get-Content test.txt) | ForEach-Object {$ _ -замінити "foo", "bar"} | Set-Content test.txt
BigMomma

6
Дивіться відповідь від @Rachel:powershell -Command "(gc myFile.txt) -replace 'foo', 'bar' | sc myFile.txt"
Nigel Touch

161

Просто використовували ФАРТ ( « Р Ind й Р eplace Т вн» утиліта командного рядка):
відмінна маленька безкоштовна програма для заміни тексту в великому наборі файлів.

Файли налаштування знаходяться на SourceForge .

Приклад використання:

fart.exe -p -r -c -- C:\tools\perl-5.8.9\* @@APP_DIR@@ C:\tools

буде переглядати заміни, щоб зробити рекурсивно у файлах цього дистрибутива Perl.

Єдина проблема: піктограма веб-сайту FART не зовсім зі смаком, вишуканістю чи елегантністю;)


Оновлення 2017 (7 років пізніше) Джагб вказує у коментарях до статті 2011 року " FARTING the Easy Way - Find and Replace Text " від Mikail Tunç


19
Класна річ - це один єдиний екзе. Ніяких залежностей. Немає дрібних відбитків. Супер легко розгортати.
Серж Вотьє

2
Дуже легкий і простий у використанні, але я сподівався, що він роздрукує точні місця, в яких відбулася заміна. Неможливо побачити, що викликало у мене почуття незахищеності.
Вільям Ніу

4
Дякую, це ідеально, повинно бути частиною стандартних інструментів дос і спрацювало привабливість. Опція -p, однак, не показує, скільки змін "зробить", і завжди повідомляє 0, що кинуло мене на кілька хвилин
sradforth

3
Я розумію, що це дуже давнє запитання, але я знайшов більше інформації і сподіваюся, що це буде корисно для користувачів Stack Overflow. Ще одне посилання на FART, де продукт добре пояснений: FART пояснив @ emtunc.org та іншу сторінку можна знайти тут: FART Будьте уважні із заміною, /і 'оскільки це працює не для всіх нас , для мене він працював у деяких випадків, але він не працював на деяких файлах, і я не знаю, чому .. Я використовував це для заміни тексту на інший текст і/
jagb

4
@jagb Дякую Я включив ваше посилання у відповідь для більшої наочності.
VonC

128

Замінити - Замініть підрядку за допомогою підстановки рядків Опис: Щоб замінити підрядку на іншу рядок, використовуйте функцію підстановки рядків. Наведений тут приклад замінює всі випадки написання помилок "teh" на "the" у рядковій змінній str.

set str=teh cat in teh hat
echo.%str%
set str=%str:teh=the%
echo.%str%

Вихід сценарію:

teh cat in teh hat
the cat in the hat

ref: http://www.dostips.com/DtTipsStringManipulation.php#Snippets.Replace


30
Як пропозиція sed краще? Здається, це найпростіша відповідь на них усіх і нічого не вимагає встановлювати.
DonBecker

5
Чи можна тут зробити будь-яке узгодження шаблону? Wildcards, Regex тощо?
Кейо

27
"Як краще пропозиція sed?" - sed і подібні утиліти працюють на файли; цей фрагмент опускає важливий крок зчитування рядків з вхідного файлу та запису до вихідного файлу, забезпечуючи при цьому правильність обробки будь-яких спеціальних символів у файлі.
Джо

7
@Asad, так, це правда, ОП запитувала про файли, але насправді це працює з потоками, які не повинні бути файлами. Але моя думка в тому, що ця відповідь є хибною, оскільки вона не дозволяє читати / писати з потоку та обробляти будь-які спеціальні символи.
Джо

4
@Bill як використовувати змінну як заміну тексту? тобто. Я маю значення в змінній і рядку, який має деякий розмежувач. set str =% str: "##" =% varValue %% не працює. Будь-які обходи?
MalTec

55

Створіть файл substitu.vbs:

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)
Set objFile = objFSO.OpenTextFile(strFileName, ForWriting)
objFile.Write strNewText  'WriteLine adds extra CR/LF
objFile.Close

Щоб використовувати цей переглянений скрипт (який ми будемо називати substitu.vbs), просто введіть команду, аналогічну цій, у командному рядку:

cscript replace.vbs "C:\Scripts\Text.txt" "Jim " "James "


це акуратно, чи дозволяє це використовувати RegEx?
користувач280109

3
@ user280109 Так, VBScript підтримує RegExp. Ви можете використовувати це , щоб замінити , використовуючи регулярний вираз: With (New RegExp): strNewText = .Replace(strText, strOldText, strNewText): End With. Ви можете отримати текст з перших 9 захоплюючих груп , використовуючи $1, $2... $9.
Зубна щітка

2
VBScript часто не помічається (і його ненавидять), але він доступний на всіх платформах Windows, дуже читабельний і насправді має дуже потужні можливості +1
zelanix

1
@ user280109 Ви тільки що дали команду, Що мені потрібно. Але я хочу замінити (нечутливий до регістру) Чи можете ви надати команду для цього?
Ajmal Praveen

49

BatchSubstitute.batна dostips.com - приклад пошуку та заміни за допомогою чистого пакетного файлу.

Він використовує комбінацію FOR, FINDі CALL SET.

Рядки, що містять символи, "&<>]|^можуть трактуватися неправильно.



8
Я маю сумніватися у корисності сайту фрагменту коду, умови використання якого забороняють копіювати будь-який код ("Ви не можете поширювати будь-яку інформацію, надану в домені dostips.com, у будь-якій формі без явного письмового дозволу власника домену.") .
Жил "ТАК - перестань бути злим"

1
Я погоджуюсь, що їхні умови заплутані, вони також кажуть "Інформація, надана в домені dostips.com, сподіваємось корисна", тому моє припущення полягає в тому, що вони раді людям скопіювати код для вирішення проблеми. Я не впевнений, що коли-небудь читав будь-які умови та був радий ...
morechilli

5
Це чудово. Я люблю відповіді, які не передбачають завантаження чогось іншого, щоб це зробити.
Ruairi O'Brien

Мені також подобаються рішення, які не включають зовнішні утиліти, на жаль, я постійно намагаюся отримати "find: invalid preicate '" ", коли я намагаюся запустити цю партію. Не дійсно встигайте зараз налагоджувати це.
Яхміч

2
Помилка "знайти: невірний предикат" '"сталася через зовнішню утиліту" знайти "в моїй системі. Після видалення це спрацювало чудово.
Яхміч

47

Примітка. Обов’язково перегляньте оновлення в кінці цієї відповіді за посиланням на вищий JREPL.BAT, який заміняє REPL.BAT
JREPL.BAT 7.0 і вище, що підтримує унікод (UTF-16LE) за допомогою /UTFопції, а також будь-який інший набір символів, включаючи UTF-8, через ADO !!!!


Я написав невелику гібридну утиліту JScript / пакетного під назвою REPL.BAT, яка дуже зручна для зміни файлів ASCII (або розширеного ASCII) через командний рядок або пакетний файл. Суто рідний сценарій не вимагає встановлення будь-якого стороннього виконуваного файлу, і він працює в будь-якій сучасній версії Windows від XP далі. Це також дуже швидко, особливо в порівнянні з чистими партійними розчинами.

REPL.BAT просто зчитує stdin, виконує пошук і заміну регексу JScript і записує результат у stdout.

Ось тривіальний приклад того, як замінити foo на бар у test.txt, якщо припустити, що REPL.BAT знаходиться у вашій поточній папці, а ще краще - десь у вашому PATH:

type test.txt|repl "foo" "bar" >test.txt.new
move /y test.txt.new test.txt

Можливості регулярного вираження JScript роблять його дуже потужним, особливо здатність тексту заміни посилатися на захоплені підрядки з тексту пошуку.

Я включив у програму ряд варіантів, які роблять її досить потужною. Наприклад, поєднання Mта Xпараметри дозволяють змінювати бінарні файли! Параметр " MБагаторядкові" дозволяє здійснювати пошук по декількох рядках. Параметр Xшаблону підстановки eXtended пропонує послідовності виходу, що дозволяють включити будь-яке бінарне значення в текст заміни.

Вся утиліта могла бути записана як чистий JScript, але гібридний пакетний файл виключає необхідність чітко вказати CSCRIPT кожного разу, коли ви хочете використовувати цю утиліту.

Ось сценарій REPL.BAT. Повна документація вбудована в сценарій.

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment

::************ Documentation ***********
::REPL.BAT version 6.2
:::
:::REPL  Search  Replace  [Options  [SourceVar]]
:::REPL  /?[REGEX|REPLACE]
:::REPL  /V
:::
:::  Performs a global regular expression search and replace operation on
:::  each line of input from stdin and prints the result to stdout.
:::
:::  Each parameter may be optionally enclosed by double quotes. The double
:::  quotes are not considered part of the argument. The quotes are required
:::  if the parameter contains a batch token delimiter like space, tab, comma,
:::  semicolon. The quotes should also be used if the argument contains a
:::  batch special character like &, |, etc. so that the special character
:::  does not need to be escaped with ^.
:::
:::  If called with a single argument of /?, then prints help documentation
:::  to stdout. If a single argument of /?REGEX, then opens up Microsoft's
:::  JScript regular expression documentation within your browser. If a single
:::  argument of /?REPLACE, then opens up Microsoft's JScript REPLACE
:::  documentation within your browser.
:::
:::  If called with a single argument of /V, case insensitive, then prints
:::  the version of REPL.BAT.
:::
:::  Search  - By default, this is a case sensitive JScript (ECMA) regular
:::            expression expressed as a string.
:::
:::            JScript regex syntax documentation is available at
:::            http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx
:::
:::  Replace - By default, this is the string to be used as a replacement for
:::            each found search expression. Full support is provided for
:::            substituion patterns available to the JScript replace method.
:::
:::            For example, $& represents the portion of the source that matched
:::            the entire search pattern, $1 represents the first captured
:::            submatch, $2 the second captured submatch, etc. A $ literal
:::            can be escaped as $$.
:::
:::            An empty replacement string must be represented as "".
:::
:::            Replace substitution pattern syntax is fully documented at
:::            http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx
:::
:::  Options - An optional string of characters used to alter the behavior
:::            of REPL. The option characters are case insensitive, and may
:::            appear in any order.
:::
:::            A - Only print altered lines. Unaltered lines are discarded.
:::                If the S options is present, then prints the result only if
:::                there was a change anywhere in the string. The A option is
:::                incompatible with the M option unless the S option is present.
:::
:::            B - The Search must match the beginning of a line.
:::                Mostly used with literal searches.
:::
:::            E - The Search must match the end of a line.
:::                Mostly used with literal searches.
:::
:::            I - Makes the search case-insensitive.
:::
:::            J - The Replace argument represents a JScript expression.
:::                The expression may access an array like arguments object
:::                named $. However, $ is not a true array object.
:::
:::                The $.length property contains the total number of arguments
:::                available. The $.length value is equal to n+3, where n is the
:::                number of capturing left parentheses within the Search string.
:::
:::                $[0] is the substring that matched the Search,
:::                $[1] through $[n] are the captured submatch strings,
:::                $[n+1] is the offset where the match occurred, and
:::                $[n+2] is the original source string.
:::
:::                Arguments $[0] through $[10] may be abbreviated as
:::                $1 through $10. Argument $[11] and above must use the square
:::                bracket notation.
:::
:::            L - The Search is treated as a string literal instead of a
:::                regular expression. Also, all $ found in the Replace string
:::                are treated as $ literals.
:::
:::            M - Multi-line mode. The entire contents of stdin is read and
:::                processed in one pass instead of line by line, thus enabling
:::                search for \n. This also enables preservation of the original
:::                line terminators. If the M option is not present, then every
:::                printed line is terminated with carriage return and line feed.
:::                The M option is incompatible with the A option unless the S
:::                option is also present.
:::
:::                Note: If working with binary data containing NULL bytes,
:::                      then the M option must be used.
:::
:::            S - The source is read from an environment variable instead of
:::                from stdin. The name of the source environment variable is
:::                specified in the next argument after the option string. Without
:::                the M option, ^ anchors the beginning of the string, and $ the
:::                end of the string. With the M option, ^ anchors the beginning
:::                of a line, and $ the end of a line.
:::
:::            V - Search and Replace represent the name of environment
:::                variables that contain the respective values. An undefined
:::                variable is treated as an empty string.
:::
:::            X - Enables extended substitution pattern syntax with support
:::                for the following escape sequences within the Replace string:
:::
:::                \\     -  Backslash
:::                \b     -  Backspace
:::                \f     -  Formfeed
:::                \n     -  Newline
:::                \q     -  Quote
:::                \r     -  Carriage Return
:::                \t     -  Horizontal Tab
:::                \v     -  Vertical Tab
:::                \xnn   -  Extended ASCII byte code expressed as 2 hex digits
:::                \unnnn -  Unicode character expressed as 4 hex digits
:::
:::                Also enables the \q escape sequence for the Search string.
:::                The other escape sequences are already standard for a regular
:::                expression Search string.
:::
:::                Also modifies the behavior of \xnn in the Search string to work
:::                properly with extended ASCII byte codes.
:::
:::                Extended escape sequences are supported even when the L option
:::                is used. Both Search and Replace support all of the extended
:::                escape sequences if both the X and L opions are combined.
:::
:::  Return Codes:  0 = At least one change was made
:::                     or the /? or /V option was used
:::
:::                 1 = No change was made
:::
:::                 2 = Invalid call syntax or incompatible options
:::
:::                 3 = JScript runtime error, typically due to invalid regex
:::
::: REPL.BAT was written by Dave Benham, with assistance from DosTips user Aacini
::: to get \xnn to work properly with extended ASCII byte codes. Also assistance
::: from DosTips user penpen diagnosing issues reading NULL bytes, along with a
::: workaround. REPL.BAT was originally posted at:
::: http://www.dostips.com/forum/viewtopic.php?f=3&t=3855
:::

::************ Batch portion ***********
@echo off
if .%2 equ . (
  if "%~1" equ "/?" (
    <"%~f0" cscript //E:JScript //nologo "%~f0" "^:::" "" a
    exit /b 0
  ) else if /i "%~1" equ "/?regex" (
    explorer "http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx"
    exit /b 0
  ) else if /i "%~1" equ "/?replace" (
    explorer "http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx"
    exit /b 0
  ) else if /i "%~1" equ "/V" (
    <"%~f0" cscript //E:JScript //nologo "%~f0" "^::(REPL\.BAT version)" "$1" a
    exit /b 0
  ) else (
    call :err "Insufficient arguments"
    exit /b 2
  )
)
echo(%~3|findstr /i "[^SMILEBVXAJ]" >nul && (
  call :err "Invalid option(s)"
  exit /b 2
)
echo(%~3|findstr /i "M"|findstr /i "A"|findstr /vi "S" >nul && (
  call :err "Incompatible options"
  exit /b 2
)
cscript //E:JScript //nologo "%~f0" %*
exit /b %errorlevel%

:err
>&2 echo ERROR: %~1. Use REPL /? to get help.
exit /b

************* JScript portion **********/
var rtn=1;
try {
  var env=WScript.CreateObject("WScript.Shell").Environment("Process");
  var args=WScript.Arguments;
  var search=args.Item(0);
  var replace=args.Item(1);
  var options="g";
  if (args.length>2) options+=args.Item(2).toLowerCase();
  var multi=(options.indexOf("m")>=0);
  var alterations=(options.indexOf("a")>=0);
  if (alterations) options=options.replace(/a/g,"");
  var srcVar=(options.indexOf("s")>=0);
  if (srcVar) options=options.replace(/s/g,"");
  var jexpr=(options.indexOf("j")>=0);
  if (jexpr) options=options.replace(/j/g,"");
  if (options.indexOf("v")>=0) {
    options=options.replace(/v/g,"");
    search=env(search);
    replace=env(replace);
  }
  if (options.indexOf("x")>=0) {
    options=options.replace(/x/g,"");
    if (!jexpr) {
      replace=replace.replace(/\\\\/g,"\\B");
      replace=replace.replace(/\\q/g,"\"");
      replace=replace.replace(/\\x80/g,"\\u20AC");
      replace=replace.replace(/\\x82/g,"\\u201A");
      replace=replace.replace(/\\x83/g,"\\u0192");
      replace=replace.replace(/\\x84/g,"\\u201E");
      replace=replace.replace(/\\x85/g,"\\u2026");
      replace=replace.replace(/\\x86/g,"\\u2020");
      replace=replace.replace(/\\x87/g,"\\u2021");
      replace=replace.replace(/\\x88/g,"\\u02C6");
      replace=replace.replace(/\\x89/g,"\\u2030");
      replace=replace.replace(/\\x8[aA]/g,"\\u0160");
      replace=replace.replace(/\\x8[bB]/g,"\\u2039");
      replace=replace.replace(/\\x8[cC]/g,"\\u0152");
      replace=replace.replace(/\\x8[eE]/g,"\\u017D");
      replace=replace.replace(/\\x91/g,"\\u2018");
      replace=replace.replace(/\\x92/g,"\\u2019");
      replace=replace.replace(/\\x93/g,"\\u201C");
      replace=replace.replace(/\\x94/g,"\\u201D");
      replace=replace.replace(/\\x95/g,"\\u2022");
      replace=replace.replace(/\\x96/g,"\\u2013");
      replace=replace.replace(/\\x97/g,"\\u2014");
      replace=replace.replace(/\\x98/g,"\\u02DC");
      replace=replace.replace(/\\x99/g,"\\u2122");
      replace=replace.replace(/\\x9[aA]/g,"\\u0161");
      replace=replace.replace(/\\x9[bB]/g,"\\u203A");
      replace=replace.replace(/\\x9[cC]/g,"\\u0153");
      replace=replace.replace(/\\x9[dD]/g,"\\u009D");
      replace=replace.replace(/\\x9[eE]/g,"\\u017E");
      replace=replace.replace(/\\x9[fF]/g,"\\u0178");
      replace=replace.replace(/\\b/g,"\b");
      replace=replace.replace(/\\f/g,"\f");
      replace=replace.replace(/\\n/g,"\n");
      replace=replace.replace(/\\r/g,"\r");
      replace=replace.replace(/\\t/g,"\t");
      replace=replace.replace(/\\v/g,"\v");
      replace=replace.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
        function($0,$1,$2){
          return String.fromCharCode(parseInt("0x"+$0.substring(2)));
        }
      );
      replace=replace.replace(/\\B/g,"\\");
    }
    search=search.replace(/\\\\/g,"\\B");
    search=search.replace(/\\q/g,"\"");
    search=search.replace(/\\x80/g,"\\u20AC");
    search=search.replace(/\\x82/g,"\\u201A");
    search=search.replace(/\\x83/g,"\\u0192");
    search=search.replace(/\\x84/g,"\\u201E");
    search=search.replace(/\\x85/g,"\\u2026");
    search=search.replace(/\\x86/g,"\\u2020");
    search=search.replace(/\\x87/g,"\\u2021");
    search=search.replace(/\\x88/g,"\\u02C6");
    search=search.replace(/\\x89/g,"\\u2030");
    search=search.replace(/\\x8[aA]/g,"\\u0160");
    search=search.replace(/\\x8[bB]/g,"\\u2039");
    search=search.replace(/\\x8[cC]/g,"\\u0152");
    search=search.replace(/\\x8[eE]/g,"\\u017D");
    search=search.replace(/\\x91/g,"\\u2018");
    search=search.replace(/\\x92/g,"\\u2019");
    search=search.replace(/\\x93/g,"\\u201C");
    search=search.replace(/\\x94/g,"\\u201D");
    search=search.replace(/\\x95/g,"\\u2022");
    search=search.replace(/\\x96/g,"\\u2013");
    search=search.replace(/\\x97/g,"\\u2014");
    search=search.replace(/\\x98/g,"\\u02DC");
    search=search.replace(/\\x99/g,"\\u2122");
    search=search.replace(/\\x9[aA]/g,"\\u0161");
    search=search.replace(/\\x9[bB]/g,"\\u203A");
    search=search.replace(/\\x9[cC]/g,"\\u0153");
    search=search.replace(/\\x9[dD]/g,"\\u009D");
    search=search.replace(/\\x9[eE]/g,"\\u017E");
    search=search.replace(/\\x9[fF]/g,"\\u0178");
    if (options.indexOf("l")>=0) {
      search=search.replace(/\\b/g,"\b");
      search=search.replace(/\\f/g,"\f");
      search=search.replace(/\\n/g,"\n");
      search=search.replace(/\\r/g,"\r");
      search=search.replace(/\\t/g,"\t");
      search=search.replace(/\\v/g,"\v");
      search=search.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
        function($0,$1,$2){
          return String.fromCharCode(parseInt("0x"+$0.substring(2)));
        }
      );
      search=search.replace(/\\B/g,"\\");
    } else search=search.replace(/\\B/g,"\\\\");
  }
  if (options.indexOf("l")>=0) {
    options=options.replace(/l/g,"");
    search=search.replace(/([.^$*+?()[{\\|])/g,"\\$1");
    if (!jexpr) replace=replace.replace(/\$/g,"$$$$");
  }
  if (options.indexOf("b")>=0) {
    options=options.replace(/b/g,"");
    search="^"+search
  }
  if (options.indexOf("e")>=0) {
    options=options.replace(/e/g,"");
    search=search+"$"
  }
  var search=new RegExp(search,options);
  var str1, str2;

  if (srcVar) {
    str1=env(args.Item(3));
    str2=str1.replace(search,jexpr?replFunc:replace);
    if (!alterations || str1!=str2) if (multi) {
      WScript.Stdout.Write(str2);
    } else {
      WScript.Stdout.WriteLine(str2);
    }
    if (str1!=str2) rtn=0;
  } else if (multi){
    var buf=1024;
    str1="";
    while (!WScript.StdIn.AtEndOfStream) {
      str1+=WScript.StdIn.Read(buf);
      buf*=2
    }
    str2=str1.replace(search,jexpr?replFunc:replace);
    WScript.Stdout.Write(str2);
    if (str1!=str2) rtn=0;
  } else {
    while (!WScript.StdIn.AtEndOfStream) {
      str1=WScript.StdIn.ReadLine();
      str2=str1.replace(search,jexpr?replFunc:replace);
      if (!alterations || str1!=str2) WScript.Stdout.WriteLine(str2);
      if (str1!=str2) rtn=0;
    }
  }
} catch(e) {
  WScript.Stderr.WriteLine("JScript runtime error: "+e.message);
  rtn=3;
}
WScript.Quit(rtn);

function replFunc($0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10) {
  var $=arguments;
  return(eval(replace));
}


ВАЖЛИВА ОНОВЛЕННЯ

Я припинив розробку REPL.BAT і замінив її на JREPL.BAT. Ця нова утиліта має все той же функціонал REPL.BAT, а також багато іншого:

  • Підтримка Unicode UTF-16LE за допомогою унікальних можливостей Unicode CSCRIPT та будь-якого іншого набору символів (включаючи UTF-8) через ADO.
  • Читайте безпосередньо з / записуйте безпосередньо у файл: немає необхідності в трубах, перенаправленнях або переміщенні команди.
  • Включити JScript з користувачем
  • Засіб перекладу, подібний до unix tr, тільки він також підтримує пошук регулярних виразів та JScript заміни
  • Відмовтеся від невідповідного тексту
  • Префіксні вихідні рядки з номером рядка
  • і більше...

Як завжди, повна документація вбудована в сценарій.

Оригінальне банальне рішення тепер ще простіше:

jrepl "foo" "bar" /f test.txt /o -

Поточна версія JREPL.BAT доступна на DosTips . Прочитайте всі наступні публікації в потоці, щоб побачити приклади використання та історію розвитку.


Чудові речі! Мені подобається ця тематика простоти і те, як ви можете адаптувати її до будь-якого сценарію, отже, писати JS-код, ніж шалену партію.
Адаптабі

Редагувати - Додана опція A лише для змін друкованих рядків. Також було вдосконалено опцію X для підтримки \qпредставлення ", а пошукові літерали тепер підтримують усі розширені послідовності відключення, коли параметри L і X поєднуються.
dbenham

@dbenham - +1. Це тонкий підхід, він стане в нагоді і для кількох інших завдань. Дякуємо за публікацію
bw

EDIT - я змінив поведінку \ xnn, коли використовується параметр X, щоб код представляв розширений байт-код ASCII. Також додано опцію версії V / V.
dbenham

9
@dbenham Це дорогоцінний камінь. Чому б ти не поставив це на GitHub або як Gist? Полегшать версію, подальші дії, випуски / розповсюдження, виправлення та ін. Якщо вам потрібна допомога з цим, дайте мені знати.
Атіф Азіз

36

Використовуйте FNR

Використовуйте fnrутиліту. Це має деякі переваги перед fart:

  • Регулярні вирази
  • Необов’язковий графічний інтерфейс. Має "Створити кнопку командного рядка" для створення тексту командного рядка, який слід помістити в пакетний файл.
  • Багатолінійні візерунки: графічний інтерфейс дозволяє легко працювати з багатолінійними візерунками. У FART вам доведеться вручну уникнути розривів лінії.
  • Дозволяє вибрати кодування текстових файлів. Також є опція автоматичного виявлення.

Завантажити FNR тут: http://findandreplace.io/?z=codeplex

Приклад використання: fnr --cl --dir "<Directory Path>" --fileMask "hibernate.*" --useRegEx --find "find_str_expression" --replace "replace_string"


1
Це добре. Можливість генерувати командний рядок з gui - це приємна проста функція, яка швидко змусила мене йти.
Девід Хаммонд

Дуже корисний засіб. Спробував FART раніше, але документація застаріла.
Артур Кендзьор

Класний інструмент, він навіть підтримує регулярне вираження. Це те, чого FART не вистачає.
Діо Пхунг

1
Дякуємо, що вказали на цей інструмент. Single exe, чудова заміна для FART, який більше не розробляється (і не вистачає регулярного вираження); а синтаксис PowerShell - це нестерпно.
Гра "Двомісний"

Це найкорисніше. Шукав заміну grep + sed у windows, це спрацювало чудово!
Сербан Танаса

25

Я не думаю, що існує спосіб зробити це за допомогою будь-яких вбудованих команд. Я б запропонував вам завантажити щось на зразок Gnuwin32 або UnxUtils і скористатися sedкомандою (або лише завантажити sed):

sed -c s/FOO/BAR/g filename

2
Використовуйте cygwin ( cygwin.com ). Наступне найкраще - фактично встановити Linux.
Ендрю Джонсон

Краще, якщо можна запропонувати рішення, яке не покладається на встановлення cygwin. POSIX-маніпуляція з рядком не є розумною - це робити в Windows трохи незрозуміліше.
Рекс

4
Gnuwin32 та UnxUtils - це окремі бінарні файли, створені для Windows. Вони не залежать від цигуна.
Ferruccio

1
cygwin: sed -i -b -e 's/FOO/BAR/g' `find . -name *.txt`-i - редагувати файл на місці; -b - не обробляти CR + LF - без цієї опції CR + LF буде перетворено на LF
Олексій Вишенцев

@AndrewJohnson Думка та інформація - це дві різні речі.
Preza8

21

Я знаю, що я спізнююсь на вечірку ..

Особисто мені подобається рішення за адресою: - http://www.dostips.com/DtTipsStringManipulation.php#Snippets.Replace

Ми також широко використовуємо функцію дедупі, щоб допомогти нам доставляти приблизно 500 електронних листів щодня через SMTP з: - https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/sj8IUhMOq6o

і вони обидва працюють у домашніх умовах без додаткових інструментів чи утиліт.

ПОМОЩНИК:

DEL New.txt
setLocal EnableDelayedExpansion
For /f "tokens=* delims= " %%a in (OLD.txt) do (
Set str=%%a
set str=!str:FOO=BAR!
echo !str!>>New.txt
)
ENDLOCAL

ДЕДУПЛІКАТОР (зверніть увагу на використання -9 для номера ABA):

REM DE-DUPLICATE THE Mapping.txt FILE
REM THE DE-DUPLICATED FILE IS STORED AS new.txt

set MapFile=Mapping.txt
set ReplaceFile=New.txt

del %ReplaceFile%
::DelDupeText.bat
rem https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/sj8IUhMOq6o
setLocal EnableDelayedExpansion
for /f "tokens=1,2 delims=," %%a in (%MapFile%) do (
set str=%%a
rem Ref: http://www.dostips.com/DtTipsStringManipulation.php#Snippets.RightString
set str=!str:~-9!
set str2=%%a
set str3=%%a,%%b

find /i ^"!str!^" %MapFile%
find /i ^"!str!^" %ReplaceFile%
if errorlevel 1 echo !str3!>>%ReplaceFile%
)
ENDLOCAL

Дякую!


пакетний сценарій не робить нічого, крім простої копії файлу - також: за що ви дякуєте собі?
спеціаліз

Початковий запит полягав у заміні "FOO" на "BAR" у текстовому файлі, використовуючи пакетний сценарій та бажано вбудовані функції. Якщо я щось подякував у публікації в групах Google, я виявив, що працює чудово, і ми його використовуємо донині. Також дивіться публікації та відповіді на кшталт цих як корисні для користувачів, які йдуть у дорогу. Я не бачу ваших коментарів щодо копіювання файлу. Звичайно, він переносить вміст одного файлу і відлунює результат в інший файл, але на основі даних він обробляє та аналізує необхідну інформацію. Я рекомендую спробувати спершу. ;)
Лептонатор

в основному це інструмент копіювання файлів, який замінює дві статичні рядки - ви могли б принаймні розмістити там дві змінні, щоб люди, які хочуть його спробувати, не повинні зрозуміти синтаксис, щоб насправді мати можливість використовувати його - також: припущення через Інтернет майже завжди абсолютно неправильні. Пам'ятайте, що.
спеціаліз

4
@specializt - Будь ласка ... Я не тут, щоб обговорювати семантику. Якщо вам подобається, чи можемо ми взяти це в автономному режимі у чаті.
Лептонатор

2
На мою думку, це відповідь на оригінальне запитання. Я буду користуватися цією порадою для налаштування файлів ініціалізації для послуги під час налаштування, і я не хотів би вмикати PowerShell або дозволити запуск двигуна сценаріїв на моїх серверах. Тому часто відповідайте на питання, пов’язані з Windows, почніть з "встановити цю штучку звідти", оскільки все ще існує "ПК".
Міко

15

Коли ви працюєте з Git в Windows, тоді просто запустіть git-bash і використовуйте sed. Або, використовуючи Windows 10, запустіть "Bash on Ubuntu в Windows" (з підсистеми Linux) та використовуйте sed.

Це редактор потоків, але може редагувати файли безпосередньо, використовуючи таку команду:

sed -i -e 's/foo/bar/g' filename
  • -i параметр використовується для редагування на місці імені файлу.
  • -e опція вказує команду для запуску.
    • sвикористовується для заміни знайденого виразу "foo" на "bar" і gвикористовується для заміни знайдених відповідностей.

Примітка ereOn:

Якщо ви хочете замінити рядок у файлах з версією лише сховища Git, ви можете скористатися:

git ls-files <eventual subfolders & filters> | xargs sed -i -e 's/foo/bar/g'

що творить чудеса.


1
Зауважте, що якщо ви справді робите це перейменування у сховищі git і хочете замінити лише оновлені файли, можливо, ви захочете зробити: git ls-files <eventual subfolders & filters> | xargs sed -i -e 's/foo/bar/g'що творить чудеса.
1616

13

Я пограв з деякими з існуючих відповідей тут і віддаю перевагу вдосконаленому рішенню ...

type test.txt | powershell -Command "$input | ForEach-Object { $_ -replace \"foo\", \"bar\" }"

або якщо ви хочете знову зберегти вихід у файл ...

type test.txt | powershell -Command "$input | ForEach-Object { $_ -replace \"foo\", \"bar\" }" > outputFile.txt

Перевага цього полягає в тому, що ви можете передавати вихід з будь-якої програми. Ми також розглянемо використання регулярних виразів і з цим. Не вдалося розібратися, як перетворити його у файл BAT для більш легкого використання, хоча ... :-(


3
Це хороше рішення. На жаль, використовуючи typeзасоби, загортаються всі рядки, що перевищують 80 символів. Який біль.
sirdank

12

Я використав perl, і це чудово працює.

perl -pi.orig -e "s/<textToReplace>/<textToReplaceWith>/g;" <fileName>

.orig - це розширення, яке додається до вихідного файлу

Для декількох файлів, які відповідають, наприклад, * .html

for %x in (<filePattern>) do perl -pi.orig -e "s/<textToReplace>/<textToReplaceWith>/g;" %x

Це найпростіше рішення +1, при переході від ш до летючої миші, просто замінити sedз perl -pi.backup -eі оцінити його :)
Yann39

11

З заміною.bat

1) З e?опцією, яка буде оцінювати спеціальні послідовності символів, як \n\rі послідовності unicode. В цьому випадку замінить цитував "Foo"і "Bar":

call replacer.bat "e?C:\content.txt" "\u0022Foo\u0022" "\u0022Bar\u0022"

2) Безпосередня заміна , де Fooі Barне котируються.

call replacer.bat "C:\content.txt" "Foo" "Bar"

це не працює для мене. Як ви це запускаєте? Я отримую помилку 'substitu_in_config.bat' не розпізнається як внутрішня чи зовнішня команда, функціонуюча програма або пакетний файл.
FrenkyB

@FrenkyB - він повинен знаходитися в тому самому каталозі, куди ви його викликаєте, або в шляху - ss64.com/nt/path.html
npocmaka

У мене були всі три файли в одному каталозі.
FrenkyB

9

Ось рішення, яке я знайшов, що працював над Win XP. У свій запущений пакетний файл я включив наступне:

set value=new_value

:: Setup initial configuration
:: I use && as the delimiter in the file because it should not exist, thereby giving me the whole line
::
echo --> Setting configuration and properties.
for /f "tokens=* delims=&&" %%a in (config\config.txt) do ( 
  call replace.bat "%%a" _KEY_ %value% config\temp.txt 
)
del config\config.txt
rename config\temp.txt config.txt

replace.batФайл , як показано нижче. Я не знайшов способу включити цю функцію в один і той же пакетний файл, тому що %%aзмінна завжди видає останнє значення в циклі for.

replace.bat:

@echo off

:: This ensures the parameters are resolved prior to the internal variable
::
SetLocal EnableDelayedExpansion

:: Replaces Key Variables
::
:: Parameters:
:: %1  = Line to search for replacement
:: %2  = Key to replace
:: %3  = Value to replace key with
:: %4  = File in which to write the replacement
::

:: Read in line without the surrounding double quotes (use ~)
::
set line=%~1

:: Write line to specified file, replacing key (%2) with value (%3)
::
echo !line:%2=%3! >> %4

:: Restore delayed expansion
::
EndLocal

1
На жаль, це також пропускає порожні рядки. Особливість команди {{для}}.
Джон Роша

7

Подивіться, чи є яка-небудь утиліта, подібна седу для cmd.exe, яка запитала еквівалент sed під Windows, також має стосуватися цього питання. Резюме:

  • Це можна зробити в пакетному файлі, але це не дуже
  • Багато доступних виконавчих файлів сторонніх розробників, які зроблять це за вас, якщо у вас є розкіш встановлення або просто копіювання через exe
  • Це можна зробити за допомогою VBScript або подібного, якщо вам потрібно щось вміти працювати на вікні Windows без змін тощо.

4

Можливо, трохи запізнюється, але я часто шукаю подібні речі, оскільки не хочу переживати біль від схвалення програмного забезпечення.

Однак ви зазвичай використовуєте оператор FOR у різних формах. Хтось створив корисний пакетний файл, який виконує пошук і заміну. Подивіться тут . Важливо зрозуміти обмеження наданого пакетного файлу. З цієї причини я не копіюю вихідний код у цій відповіді.


4

Два пакетні файли, що забезпечують search and replaceфункції, були записані членами Stack Overflow dbenhamта aaciniвикористовуютьсяnative built-in jscript в Windows.

Вони обидва robustі very swift with large filesпорівнюються зі звичайним пакетним сценарієм, а також simplerвикористовуються для основної заміни тексту. Вони обоє мають Windows regular expressionвідповідність шаблону.

  1. sed-likeВикликається цей пакетний файл-помічникrepl.bat помітний (dbenham).

    Приклад з використанням Lпрямого перемикача:

    echo This is FOO here|repl "FOO" "BAR" L
    echo and with a file:
    type "file.txt" |repl "FOO" "BAR" L >"newfile.txt"
    
  2. grep-likeВикликається цей пакетний файл-помічникfindrepl.bat помітний (від aacini).

    Приклад, у якому активні регулярні вирази:

    echo This is FOO here|findrepl "FOO" "BAR" 
    echo and with a file:
    type "file.txt" |findrepl "FOO" "BAR" >"newfile.txt"
    

Обидва стають потужними загальносистемними утилітами when placed in a folder that is on the path , або їх можна використовувати в одній папці з пакетним файлом, або із запиту cmd.

Вони обидва мають case-insensitiveвимикачі, а також багато інших функцій.


3

Команда Power shell працює як принадність

(
test.txt | ForEach-Object { $_ -replace "foo", "bar" } | Set-Content test2.txt
)

3

Щойно зіткнувся з подібною проблемою - "Пошук та заміна тексту у файлах", але за винятком того, що і для файлових файлів, і для пошуку / повторного використання мені потрібно використовувати регулярний вираз. Оскільки я не знайомий з Powershell і хочу зберегти свої пошуки для подальшого використання, мені потрібно щось більш "зручне для користувачів" (бажано, якщо він має графічний інтерфейс).

Отже, в той час як Гуглінг :) Я знайшов чудовий інструмент - FAR (Знайти та замінити) (не FART).

Ця маленька програма має приємний графічний інтерфейс та підтримку регулярного вираження для пошуку файлів і файлів у файлах. Лише недоцільність полягає в тому, що якщо ви хочете зберегти свої налаштування, вам потрібно запустити програму як адміністратор (принаймні, на Win7).


Це та сама відповідь, що і відповідь від 2010 @VonC У цій темі
1515

@jeb Я зазначив, що FAR - це не FART - дві різні програми з майже однаковими назвами. FAR має графічний інтерфейс і може працювати з регулярними виразами, тоді як у коментарях нижче цієї теми люди згадують, що FART не підтримує регулярний вираз.
madcorp

3

Я вважаю за краще використовувати sedвід GNU утиліта для Win32 , складається в наступному необхідно відзначити

  • одина цитата ''не працюватиме у Windows, використовуйте ""замість цього
  • sed -iне працюватиме у Windows, знадобиться підміна файлів

Тож робочий код sedпошуку та заміни тексту у файлі у Windows є таким, як показано нижче

sed -e "s/foo/bar/g" test.txt > tmp.txt && mv tmp.txt test.txt

2
Перед тим, як користувачі Windows негайно виконають заміну файлів: новіші версії sed підтримують редагування на місці -i! Якщо ваша версія sed є, то перевірте команду з цієї відповіді: stackoverflow.com/a/33762001/2492801 .
Бенджамін Білер

2

Це одне, що пакетні сценарії просто не дуже добре.

Сценарій morechilli, з яким пов'язано, буде працювати для деяких файлів, але, на жаль, він задихнеться на ті, що містять символи, такі як труби та амперсанди.

VBScript є кращим вбудованим інструментом для виконання цього завдання. Приклад див. У цій статті: http://www.microsoft.com/technet/scriptcenter/resources/qanda/feb05/hey0208.mspx


2

@Rachel дав чудову відповідь, але ось його варіант для читання вмісту до $dataзмінної powerhell . Потім ви можете легко маніпулювати вмістом кілька разів перед записом у вихідний файл. Також дивіться, як багаторядкові значення задаються у пакетних файлах .bat.

@REM ASCII=7bit ascii(no bom), UTF8=with bom marker
set cmd=^
  $old = '\$Param1\$'; ^
  $new = 'Value1'; ^
  [string[]]$data = Get-Content 'datafile.txt'; ^
  $data = $data -replace $old, $new; ^
  out-file -InputObject $data -encoding UTF8 -filepath 'datafile.txt';
powershell -NoLogo -Noninteractive -InputFormat none -Command "%cmd%"

2

Використовуйте powershell в .bat - для Windows 7+

кодування utf8 необов'язково, добре для веб-сайтів

@echo off
set ffile='myfile.txt'
set fold='FOO'
set fnew='BAR'
powershell -Command "(gc %ffile%) -replace %fold%, %fnew% | Out-File %ffile% -encoding utf8"

1

Завантажте Cygwin (безкоштовно) та використовуйте команди, схожі на unix, у командному рядку Windows.

Ваша найкраща ставка: sed


10
Цигвін - зло. Не встановлюйте його. Краще використовувати згадані нижче UnixUtils.
zedoo

24
Що в цьому так зла?
джм.

@jm Можливо, тому що вам доведеться встановлювати всю річ разом, а не використовувати один виконуваний файл, коли хочете.
Андрі

Краще скористайтеся powerhell, він фактично вбудований у windows.
Preza8

0

Можна також переглянути інструменти «Замінити» та «Замінити фільтру» на веб- сайті https://zoomicon.github.io/tranXform/ (джерело включено). 2-й - фільтр.

Інструмент, що замінює рядки у файлах, знаходиться у VBScript (для запуску у старих версіях Windows потрібен хост Windows Script [WSH])

Фільтр, ймовірно, не працює з Unicode, якщо ви не перекомпілюєте з останніми Delphi (або з FreePascal / Lazarus)


-5

Я стикався з цією проблемою кілька разів під час кодування під Visual C ++. Якщо у вас є, ви можете скористатися Visual studio Знайти та замінити утиліту. Це дозволяє вибрати папку та замінити вміст будь-якого файлу в цій папці будь-яким іншим текстом, який ви хочете.

У розділі Visual Studio: Редагувати -> Знайти та замінити У відкритому діалоговому вікні виберіть папку та заповніть поля "Знайти що" та "Замінити на". Сподіваюся, що це буде корисно.


2
Наджіб, ваша відповідь не допомагає користувачеві, оскільки ви припускаєте, що вони використовують програмне забезпечення, про яке вони не згадують. Запропонуйте варіант, який не потребує програмного забезпечення.
Ейрбій

@Aibrean відповідь не корисна, але не з цієї причини, це вхідна точка, яка неправильна.
Павло
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.