Как найти и заменить текст в файле, используя среду командной строки 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, в начале файла может появиться метка порядка байтов, которая не появилась в оригинале.
Wyck
78
@ Вайк Мне понадобилось время, чтобы понять, куда положить -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
Это приведет к ошибке при использовании файла, если вы сохраните в тот же файл. Вам нужно изменить команду powershell на: (Get-Content test.txt) | ForEach-Object {$ _ -replace "foo", "bar"} | Set-Content test.txt
BigMomma
6
Смотрите ответ от @Rachel:powershell -Command "(gc myFile.txt) -replace 'foo', 'bar' | sc myFile.txt"
Найджел
161

Только что использованный FART ( утилита командной строки " F ind A nd R eplace T ext"):
отличная бесплатная программа для замены текста в большом наборе файлов.

Установочные файлы находятся на SourceForge .

Пример использования:

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

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

Единственная проблема: иконка сайта FART не совсем со вкусом, изысканно или элегантно;)


Обновление 2017 года (7 лет спустя) Jagb отмечает в комментариях к статье 2011 года « FARTing the Easy Way - найдите и замените текст » от Mikail Tunç

VonC
источник
19
Крутая вещь, это один единственный exe. Нет зависимостей. Нет маленьких отпечатков. Супер легко развернуть.
Серж Вотье,
2
Очень легкий и простой в использовании, но я надеялся, что он распечатает точные места замены. Невозможность увидеть это дала мне чувство незащищенности.
Уильям Ниу
4
Спасибо, это прекрасно, должно быть частью стандартных инструментов ДОС и сработало очарование. Опция -p, однако, не показывает, сколько изменений она «сделает», и всегда сообщает 0, что меня отбросило на несколько минут
sradforth
3
Я понимаю, что это очень старый вопрос, но я нашел больше информации и надеюсь, что он будет полезен для пользователей Stack Overflow. Просто еще одна ссылка для FART, где продукт хорошо объяснен: FART объяснено @ emtunc.org, а другую страницу можно найти здесь: FART Пожалуйста, будьте осторожны с заменой, /и 'поскольку это не работает для всех нас , для меня это работало в некоторых случаи, но он не работал на некоторых файлах, и я не знаю почему .. Я использовал это, чтобы заменить текст другим текстом и/
jagb
4
@jagb Спасибо. Я включил вашу ссылку в ответ для большей наглядности.
VonC
128

Заменить - заменить подстроку с помощью подстановки строк. Описание: для замены подстроки другой строкой используйте функцию подстановки строк. Показанный здесь пример заменяет все вхождения «те» орфографические ошибки на «в» в строковой переменной 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

ссылка: http://www.dostips.com/DtTipsStringManipulation.php#Snippets.Replace

Билл Ричардсон
источник
30
Чем лучше предложение sed? Это, кажется, самый простой ответ из всех и ничего не требует установки.
DonBecker
5
Можно ли здесь выполнить какое-либо сопоставление с образцом? Подстановочные знаки, регулярные выражения и т. Д.?
Keyo
27
"Как лучше предложение sed?" - sed и подобные утилиты работают с файлами; в этом фрагменте пропущен важный этап чтения строк из входного файла и записи в выходной файл, при этом гарантируется правильная обработка любых специальных символов в файле.
Джо
7
@Asad, да, это правда, ОП спрашивал о файлах, но на самом деле он работает с потоками, которые не обязательно должны быть файлами. Но моя точка зрения заключается в том, что этот ответ ошибочен, так как он исключает чтение / запись из потока и обработку любых специальных символов.
Джо,
4
@ Как использовать переменную в качестве заменяющего текста? то есть. У меня есть значение в переменной и строка, которая имеет некоторый разделитель. set str =% str: "##" =% varValue %% не работает. Есть обходные пути?
MalTec
55

Создайте файл replace.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

Чтобы использовать этот пересмотренный скрипт (который мы будем называть replace.vbs), просто наберите в командной строке команду, похожую на эту:

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

user459118
источник
это аккуратно, это позволяет использовать RegEx?
user280109
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 Вы только что дали команду, Что мне нужно. Но я хочу заменить (без учета регистра). Можете ли вы предоставить команду для этого?
Аджмал Правин
49

BatchSubstitute.batНа dostips.com приведен пример поиска и замены с использованием чистого командного файла.

Он использует комбинацию FOR, FINDи CALL SET.

Строки, содержащие символы среди, "&<>]|^могут быть обработаны неправильно.


morechilli
источник
8
Я должен подвергнуть сомнению полезность сайта с фрагментами кода, условия использования которого запрещают копировать любой код («Вы не можете распространять любую информацию, предоставленную в домене dostips.com, в любой форме без письменного разрешения владельца домена».) ,
Жиль "ТАК - перестать быть злым"
1
Я согласен, что их условия вводят в заблуждение, они также говорят: «Информация, предоставленная в домене dostips.com, полезна», поэтому я предполагаю, что они рады, что люди скопировали код для решения проблемы. Я не уверен, что когда-либо читал какие-либо положения и условия и был счастлив ...
morechilli
5
Это замечательно. Я люблю ответы, которые не включают загрузку чего-то другого, чтобы сделать это.
Руаири О'Брайен
Мне также нравятся решения, в которых не используются внешние утилиты, к сожалению, я продолжаю получать «find: invalid предикат` »при попытке запустить этот пакет. У меня нет времени на его отладку.
Джахмик
2
Ошибка «find: invalid предиката» была вызвана внешней утилитой «find» в моей системе. После удаления это работало нормально.
Джахмик
47

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


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

REPL.BAT просто читает стандартный ввод, выполняет поиск и замену регулярных выражений JScript и записывает результат в стандартный вывод.

Вот тривиальный пример того, как заменить foo на bar в 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 предоставляет escape-последовательности, которые позволяют включать любое двоичное значение в текст замены.

Вся утилита могла бы быть написана как чистый 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 . Прочитайте все последующие сообщения в ветке, чтобы увидеть примеры использования и историю развития.

dbenham
источник
Качественный товар! Мне нравится этот б / к из-за простоты и способа, которым вы можете адаптировать его к любому сценарию, поэтому пишу код JS, а не паршивую партию.
Adaptabi
Редактировать - добавлена ​​опция A только для печати строк, которые были изменены. Также улучшена опция X для поддержки \qпредставления ", и литералы поиска теперь поддерживают все расширенные escape-последовательности, когда комбинируются опции L и X.
ДБЕНХАМ
@dbenham - +1. Это ловкий подход, он пригодится и для некоторых других задач. Спасибо за публикацию.
мт
РЕДАКТИРОВАТЬ - Я изменил поведение \ xnn при использовании опции X, чтобы код представлял расширенный байт-код ASCII. Также добавлена ​​опция версии V / V.
13
9
@dbenham Это драгоценный камень. Почему бы вам не выставить это на GitHub или в качестве Gist? Сделал бы управление версиями, последующие действия, выпуски / распространение, исправления и более простым. Если вам нужна помощь с этим, дайте мне знать.
Атиф Азиз
36

Используйте FNR

Используйте fnrутилиту. У него есть некоторые преимущества перед fart:

  • Регулярные выражения
  • Дополнительный графический интерфейс. Имеет кнопку «Создать командную строку» для создания текста командной строки для помещения в командный файл.
  • Многострочные шаблоны: GUI позволяет вам легко работать с многострочными шаблонами. В FART вы должны вручную избегать разрывов строк.
  • Позволяет выбрать кодировку текстового файла. Также есть опция автоматического определения.

Скачать FNR можно здесь: http://findandreplace.io/?z=codeplex

Пример использования: fnr --cl --dir "<Directory Path>" --fileMask "hibernate.*" --useRegEx --find "find_str_expression" --replace "replace_string"

Человек
источник
1
Это мило. Возможность генерировать командную строку из графического интерфейса - хорошая простая функция, которая заставила меня работать быстрее.
Дэвид Хаммонд
Очень полезный инструмент. Пробовал 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. Они не зависят от Cygwin.
Ферруччо
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

Спасибо!

Leptonator
источник
пакетный скрипт не делает ничего, кроме простого копирования файла, а также: почему вы благодарите себя?
специалист
Первоначальный запрос состоял в том, чтобы заменить «FOO» на «BAR» в текстовом файле, используя пакетный скрипт и, желательно, встроенные функции. Если что-то я благодарил за пост группы Google, я нашел, что работает фантастически, и мы все еще используем его по сей день. Кроме того, посты и ответы, подобные этим, также могут быть полезны для пользователей, идущих по дороге. Я не вижу ваш комментарий о копировании файла. Конечно, он берет содержимое одного файла и выводит результат в другой файл, но на основании данных он обрезает и анализирует необходимую информацию. Я бы рекомендовал сначала попробовать. ;)
Лептонатор
в основном это инструмент для копирования файлов, который заменяет две статические строки - вы могли бы по крайней мере поместить туда две переменные, так что людям, которые хотят попробовать это, не нужно понимать синтаксис для того, чтобы действительно иметь возможность использовать его - также: Предположения в Интернете почти всегда полностью неверны. Помни это.
specializt
4
@specializt - Пожалуйста ... Я здесь не для обсуждения семантики. Если хотите, можем ли мы перенести это офлайн в чат?
Лептонатор
2
На мой взгляд, это ответ на оригинальный вопрос. Я буду использовать этот совет для настройки файлов инициализации для службы во время установки, и я не хотел бы включать PowerShell или запускать механизм сценариев на моих серверах. Поэтому часто отвечайте на вопросы, связанные с Windows, начните с «установить эту штуковину оттуда», так как все еще существует отношение «ПК».
Мико
15

Когда вы работаете с Git на Windows, просто запустите git-bash и используйте sed. Или, при использовании Windows 10, запустите «Bash на 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'это работает чудесно.
ereOn
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, при конвертации из sh в bat просто замените sedна perl -pi.backup -eи оцените его :)
Yann39
11

С replacer.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"
npocmaka
источник
это не работает для меня. Как вы управляете этим? Я получаю сообщение об ошибке: replace_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

Посмотрите, есть ли какая-нибудь утилита, похожая на sed, для 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переключатели, а также много других функций.

foxidrive
источник
3

Команда Power Shell работает как шарм

(
test.txt | ForEach-Object { $_ -replace "foo", "bar" } | Set-Content test2.txt
)
kool_guy_here
источник
3

Просто столкнулся с похожей проблемой - «Поиск и замена текста в файлах», но за исключением того, что для имен файлов и поиска / переотображения мне нужно использовать регулярное выражение. Поскольку я не знаком с Powershell и хочу сохранить результаты поиска для последующего использования, мне нужно что-то более «удобное» (предпочтительно, если оно имеет графический интерфейс).

Итак, пока гуглю :) я нашел отличный инструмент - FAR (Find And Replace) (не FART).

Эта небольшая программа имеет приятный графический интерфейс и поддержку регулярных выражений для поиска в именах файлов и в файлах. Единственным недостатком является то, что если вы хотите сохранить свои настройки, вы должны запустить программу от имени администратора (по крайней мере, на Win7).

madcorp
источник
Это тот же ответ, что и ответ от 2010 @VonC В этой теме
Джеб
@jeb Я указал, что FAR - это не FART - две разные программы с почти одинаковыми именами. FAR имеет графический интерфейс и может работать с регулярным выражением, в то время как в комментариях ниже этой теме люди упоминают , что ФАРТ не поддерживает регулярные выражения.
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
Chetabahana
источник
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переменную powershell . Затем вы можете легко манипулировать контентом несколько раз перед записью в выходной файл. Также посмотрите, как многострочные значения приведены в пакетных файлах .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%"
Whome
источник
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.

Ваша лучшая ставка: сед

JM.
источник
10
Cygwin это зло. Не устанавливайте это. Лучше использовать UnixUtils, упомянутые ниже.
zedoo
24
Что в этом плохого?
Джм.
@jm Может быть потому, что вам нужно установить все вместе, а не использовать один исполняемый файл, когда вы захотите.
Андри
Лучше использовать powershell, он фактически встроен в Windows.
Preza8
0

Также можно увидеть инструменты Replace и ReplaceFilter по адресу https://zoomicon.github.io/tranXform/ (источник включен). Второй - это фильтр.

Инструмент, который заменяет строки в файлах, находится в VBScript (для работы в старых версиях Windows требуется Windows Script Host [WSH])

Фильтр, вероятно, не работает с Unicode, если вы не перекомпилируете с последней версией Delphi (или с FreePascal / Lazarus)

Джордж Бирбилис
источник
-5

Я сталкивался с этой проблемой несколько раз при кодировании под Visual C ++. Если у вас есть, вы можете использовать Visual Studio Find and Replace Utility. Это позволяет вам выбрать папку и заменить содержимое любого файла в этой папке любым другим текстом, который вы хотите.

В Visual Studio: «Правка» -> «Найти и заменить». В открывшемся диалоговом окне выберите папку и заполните поля «Найти чем» и «Заменить». Надеюсь, это будет полезно.

Наджиб
источник
2
Наджиб, ваш ответ не помогает пользователю, потому что вы предполагаете, что они используют программное обеспечение, о котором они не упоминают. Пожалуйста, предложите вариант, который не требует программного обеспечения.
Aibrean
@Aibrean ответ бесполезен, но не по этой причине, это неправильная точка входа.
Пол