Como você pode encontrar e substituir o texto em um arquivo usando o ambiente de linha de comando do Windows?

492

Estou escrevendo um script de arquivo em lotes usando o ambiente de linha de comando do Windows e quero alterar cada ocorrência de algum texto em um arquivo (por exemplo, "FOO") por outro (por exemplo, "BAR"). Qual é a maneira mais simples de fazer isso? Qualquer construído em funções?

Raio
fonte

Respostas:

308

Muitas respostas aqui me ajudaram a apontar na direção certa, mas nenhuma foi adequada para mim, por isso estou postando minha solução.

Eu tenho o Windows 7, que vem com o PowerShell embutido. Aqui está o script que eu usei para encontrar / substituir todas as instâncias de texto em um arquivo:

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

Para explicar isso:

  • powershell inicia o powershell.exe, incluído no Windows 7
  • -Command "... " é uma linha de comando arg para powershell.exe que contém o comando a ser executado
  • (gc myFile.txt)lê o conteúdo de myFile.txt( gcé abreviação de Get-Contentcomando)
  • -replace 'foo', 'bar'simplesmente executa o comando replace para substituir fooporbar
  • | Out-File myFile.txt canaliza a saída para o arquivo myFile.txt
  • -encoding ASCII impede a transcrição do arquivo de saída para unicode, como os comentários apontam

O Powershell.exe já deve fazer parte da sua instrução PATH, mas, se não, você pode adicioná-lo. A localização dele na minha máquina éC:\WINDOWS\system32\WindowsPowerShell\v1.0

Rachel
fonte
71
Cuidado, este comando também pode transcodificar o arquivo para codificação Unicode. Você pode especificar manualmente a codificação adicionando -encoding ASCIIou UTF8ou o que for necessário. Além disso, tenha cuidado, se você segmentar o UTF8, ele poderá introduzir uma marca de ordem de bytes no início do arquivo que não apareceu no original.
Wyck
78
@ Wyck Demorei um pouco para descobrir onde colocar -encoding ASCII. Para quem precisar dele no futuro, seriaOut-File -encoding ASCII myFile.txt
rwilson04
15
A única coisa que eu tinha que mudar era usar em Set-Contentvez de Out-File.
Kurtzmarc
6
Isso funciona, mas o desempenho é terrível, mesmo em uma pequena lista de arquivos.
Jsuddsjr
23
Observe que o token de substituição ('foo' nesse caso) é tratado como uma expressão regular. Se você possui algum caractere especial (eu tinha []), é necessário anexá-lo com uma \ (barra invertida).
JW
183

Se você estiver na versão do Windows compatível com .Net 2.0, eu substituirei seu shell. O PowerShell oferece todo o poder do .Net na linha de comando. Existem muitos comandos também. O exemplo abaixo resolverá sua pergunta. Estou usando os nomes completos dos comandos, existem aliases mais curtos, mas isso fornece algo para o Google.

(Get-Content test.txt) | ForEach-Object { $_ -replace "foo", "bar" } | Set-Content test2.txt
Mike Schall
fonte
10
Eu posso ver que o PowerShell é capaz de arquivar isso. Mas como posso executar isso a partir de um arquivo em lotes (exemplo: myProc.bat)?
Pablo Venturino
3
@Pablo, powershell.exe uso e comando envoltório ps no parâmetro único
Lubos Hasko
56
-1 .. Certamente a resposta foi aceita, mas não é resposta para a pergunta especificada.
baash05
28
Isso falhará com um erro de arquivo em uso, se você salvar no mesmo arquivo. Você precisa alterar o comando powershell para: (Get-Content test.txt) | ForEach-Object {$ _ - substitua "foo", "bar"} | Set-Content test.txt
BigMomma
6
Veja a resposta de @Rachel:powershell -Command "(gc myFile.txt) -replace 'foo', 'bar' | sc myFile.txt"
Nigel Touch
161

Apenas usada FART ( " F ind A nd R moran Jr. T ext" utilitário de linha de comando):
excelente gratuito pouco para substituição de texto dentro de um grande conjunto de arquivos.

Os arquivos de instalação estão no SourceForge .

Exemplo de uso:

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

irá visualizar as substituições para fazer recursivamente nos arquivos desta distribuição Perl.

Único problema: o ícone do site da FART não é exatamente de bom gosto, refinado ou elegante;)


Atualização 2017 (7 anos depois) jagb aponta nos comentários do artigo de 2011 " FARTing the Easy Way - Find And Replace Text " de Mikail Tunç

VonC
fonte
19
O legal é que é um único exe. Sem dependências. Sem letras pequenas. Super fácil de implantar.
Serge Wautier
2
Muito leve e fácil de usar, mas eu esperava que imprimisse os lugares exatos em que as substituições ocorreram. Não poder ver isso me deu uma sensação de insegurança.
William Niu
4
Obrigado, é perfeito, deve fazer parte das ferramentas padrão dos e trabalhou um charme. A opção -p, entretanto, não lhe mostrar quantas mudanças que 'iria' make e sempre relata 0 que me jogou por alguns minutos
sradforth
3
Entendo que essa é uma pergunta muito antiga, mas encontrei mais informações e espero que seja útil para os usuários do Stack Overflow. Apenas outro link para o FART, onde o produto é bem explicado: FART Explained @ emtunc.org e outra página pode ser encontrada aqui: FART Tenha cuidado com a substituição /e, 'como isso não está funcionando para todos nós , para mim funcionou em alguns casos, mas não funcionou em alguns arquivos e eu não sei porque .. Eu usei isso para substituir o texto com outro texto e uma/
jagb
4
@jagb Obrigado. Incluí seu link na resposta para obter mais visibilidade.
VonC 10/03/19
128

Substituir - Substitua uma subcadeia usando substituição de cadeia Descrição: Para substituir uma subcadeia por outra cadeia, use o recurso de substituição de cadeia. O exemplo mostrado aqui substitui todas as ocorrências "teh" com erros ortográficos por "the" na variável de string str.

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

Saída do script:

teh cat in teh hat
the cat in the hat

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

Bill Richardson
fonte
30
Como é a sugestão sed melhor? Essa parece ser a resposta mais simples de todas e requer a instalação de nada.
DonBecker
5
Qualquer tipo de correspondência de padrões pode ser feita aqui? Curingas, Regex etc?
Keyo
27
"Como a sugestão sed é melhor?" - sed e utilitários similares operam em arquivos; esse trecho omite a etapa importante de ler linhas do arquivo de entrada e gravar no arquivo de saída, garantindo que qualquer caractere especial no arquivo seja tratado corretamente.
Joe
7
@ Asad, sim, isso é verdade, o OP estava perguntando sobre arquivos, mas na verdade funciona com fluxos que não precisam ser arquivos. Mas o que quero dizer aqui é que essa resposta é falha, pois omite a leitura / gravação de um fluxo e o manuseio de caracteres especiais.
21414 Joe
4
@ Bill como usar variável como um texto de substituição? ie Eu tenho valor em uma variável e uma string que possui algum delimitador. set str =% str: "##" =% varValue %% não funciona. Alguma solução alternativa?
MalTec
55

Crie o arquivo 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

Para usar esse script revisado (que chamaremos de replace.vbs), digite um comando semelhante a este no prompt de comando:

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

user459118
fonte
isso é legal, permite o uso de RegEx?
precisa saber é o seguinte
3
@ user280109 Sim, o VBScript suporta RegExp. Você pode usar isso para substituir usando uma expressão regular: With (New RegExp): strNewText = .Replace(strText, strOldText, strNewText): End With. Você pode obter o texto dos primeiros 9 grupos de captura usando $1, $2... $9.
Escova de dentes
2
VBScript é muitas vezes esquecido (e odiado), mas está disponível em todas as plataformas Windows, é muito legível e realmente tem capacidades muito poderosas +1
zelanix
1
@ user280109 Você acabou de dar o comando: o que eu preciso. Mas eu quero substituir (sem distinção entre maiúsculas e minúsculas). Você pode fornecer o comando para isso?
precisa saber é o seguinte
49

BatchSubstitute.bat em dostips.com é um exemplo de pesquisa e substituição usando um arquivo em lote puro.

Ele usa uma combinação de FOR, FINDeCALL SET .

Linhas contendo caracteres entre "&<>]|^podem ser tratadas incorretamente.


morechilli
fonte
8
Tenho que questionar a utilidade de um site de trecho de código cujos termos de uso proíbem a cópia de qualquer código ("Você não pode distribuir nenhuma informação fornecida sob o domínio dostips.com de qualquer forma sem a permissão expressa por escrito do proprietário do domínio".) .
Gilles 'SO- stop be evil'
1
Concordo que seus termos são confusos, eles também dizem "As informações fornecidas no domínio dostips.com são esperançosamente úteis", por isso suponho que elas estejam felizes por as pessoas copiarem o código para resolver um problema. Eu não tenho certeza que eu já li todos os termos e condições e sido feliz ...
morechilli
5
Isso é ótimo. Adoro respostas que não envolvem o download de outra coisa para fazer isso.
Ruairi O'Brien
Também gosto de soluções que não envolvem utilitários externos. Infelizmente, continuo recebendo "find: predicate inválido` '"quando tento executar este lote. Realmente não tem tempo para depurá-lo agora.
Jahmic
2
O erro "localizar: predicado inválido ''" ocorreu devido a um utilitário externo 'localizar' no meu sistema. Uma vez removido, funcionou bem.
Jahmic
47

Nota - Não deixe de ver a atualização no final desta resposta para obter um link para o JREPL.BAT superior que substitui o REPL.BAT
JREPL.BAT 7.0 e superior, que suporta nativamente unicode (UTF-16LE) por meio da /UTFopção, assim como qualquer outro conjunto de caracteres, incluindo UTF-8, via ADO !!!!


Eu escrevi um pequeno utilitário JScript / lote híbrido chamado REPL.BAT que é muito conveniente para modificar arquivos ASCII (ou ASCII estendido) por meio da linha de comando ou de um arquivo em lotes. O script puramente nativo não requer a instalação de nenhum executável de terceiros e funciona em qualquer versão moderna do Windows a partir do XP. Também é muito rápido, especialmente quando comparado a soluções em lote puras.

O REPL.BAT simplesmente lê stdin, executa uma pesquisa e substituição de regex JScript e grava o resultado em stdout.

Aqui está um exemplo trivial de como substituir foo por bar no test.txt, assumindo que REPL.BAT está na sua pasta atual ou, melhor ainda, em algum lugar do seu PATH:

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

Os recursos de regex JScript o tornam muito poderoso, especialmente a capacidade do texto de substituição de referenciar substrings capturados do texto de pesquisa.

Incluí várias opções no utilitário que o tornam bastante poderoso. Por exemplo, combinar as opções Me Xpermite a modificação de arquivos binários! A Mopção Multi-line permite pesquisas em várias linhas. A Xopção padrão de substituição eXtended fornece sequências de escape que permitem a inclusão de qualquer valor binário no texto de substituição.

O utilitário inteiro pode ter sido gravado como JScript puro, mas o arquivo em lote híbrido elimina a necessidade de especificar explicitamente o CSCRIPT toda vez que você deseja usar o utilitário.

Aqui está o script REPL.BAT. A documentação completa está incorporada no script.

@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));
}


ATUALIZAÇÃO IMPORTANTE

Interrompi o desenvolvimento do REPL.BAT e o substituí pelo JREPL.BAT. Este utilitário mais recente tem todas as mesmas funcionalidades do REPL.BAT, além de muito mais:

  • Suporte Unicode UTF-16LE por meio de recursos unicode CSCRIPT nativos e qualquer outro conjunto de caracteres (incluindo UTF-8) via ADO.
  • Leia diretamente de / grave diretamente em um arquivo: não há necessidade de canais, redirecionamento ou comando de movimentação.
  • Incorporar JScript fornecido pelo usuário
  • Recurso de tradução semelhante ao unix tr, mas também suporta pesquisa regex e substituição de JScript
  • Descartar texto não correspondente
  • Prefixar linhas de saída com número de linha
  • e mais...

Como sempre, a documentação completa é incorporada ao script.

A solução trivial original agora é ainda mais simples:

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

A versão atual do JREPL.BAT está disponível no DosTips . Leia todas as postagens subsequentes no segmento para ver exemplos de uso e um histórico do desenvolvimento.

dbenham
fonte
Coisas boas! Eu amo este b / c da simplicidade e da maneira como você pode adaptá-lo a qualquer script, portanto, escrevendo código JS do que um lote ruim.
Adaptabi
Editar - Adicionada a opção A para imprimir apenas as linhas que foram modificadas. Também aprimorou a opção X para suportar \qa representação ", e os literais de Pesquisa agora suportam todas as seqüências de escape estendidas quando as opções L e X são combinadas.
dbenham
@dbenham - +1. Essa é uma abordagem inteligente, que também será útil para várias outras tarefas. Obrigado por publicá-lo.
bw
EDIT - Modifiquei o comportamento de \ xnn quando a opção X é usada para que o código represente o código de bytes ASCII estendido. Também foi adicionada uma opção de versão / V.
dbenham
9
@dbenham Esta é uma jóia. Por que você não coloca no GitHub ou como um Gist? Facilitaria o controle de versão, acompanhamento, lançamentos / distribuição, correções e muito mais. Se precisar de ajuda com isso, me avise.
Atif Aziz
36

Use FNR

Use o fnrutilitário. Tem algumas vantagens sobre fart:

  • Expressões regulares
  • GUI opcional. Possui um "botão Gerar linha de comando" para criar o texto da linha de comando para colocar no arquivo em lotes.
  • Padrões de várias linhas: a GUI permite que você trabalhe facilmente com padrões de várias linhas. No FART, você teria que escapar manualmente das quebras de linha.
  • Permite selecionar a codificação do arquivo de texto. Também possui uma opção de detecção automática.

Faça o download do FNR aqui: http://findandreplace.io/?z=codeplex

Exemplo de uso: fnr --cl --dir "<Directory Path>" --fileMask "hibernate.*" --useRegEx --find "find_str_expression" --replace "replace_string"

Um homem
fonte
1
Isso é legal. Ser capaz de gerar a linha de comando a partir da GUI é um recurso simples e agradável que me fez avançar rapidamente.
David Hammond
Ferramenta muito útil Tentei o FART antes, mas a documentação está desatualizada.
Artur Kędzior
Ferramenta legal, suporta até expressões regulares. Isso é algo que está faltando no FART.
Dio Phung
1
Obrigado por indicar esta ferramenta. Exe único, ótimo substituto para o FART, que não é mais desenvolvido (e perde regex); e a sintaxe do PowerShell é tão insuportável.
Gras Double
Isso é muito útil. Estava procurando grep + sed substituição no windows, isso funcionou muito bem!
Serban Tanasa
25

Eu não acho que haja uma maneira de fazer isso com quaisquer comandos internos. Eu sugiro que você baixe algo como Gnuwin32 ou UnxUtils e use o sedcomando (ou faça o download apenas sed):

sed -c s/FOO/BAR/g filename
Ferruccio
fonte
2
Use o cygwin ( cygwin.com ). É a próxima melhor coisa para instalar o Linux.
Andrew Johnson
É melhor se você puder fornecer uma solução que não dependa da instalação do cygwin. A manipulação de seqüências de caracteres POSIX é fácil - fazer isso no Windows é um pouco mais obscuro.
Rex
4
Gnuwin32 e UnxUtils são binários autônomos criados para Windows. Eles não são dependentes do cygwin.
Ferruccio
1
cygwin: sed -i -b -e 's/FOO/BAR/g' `find . -name *.txt`-i - edita o arquivo no local; -b - não processar CR + LF - sem esta opção CR + LF seria convertido para LF
Alexey Vishentsev
@AndrewJohnson Opinião e informação são duas coisas diferentes.
Preza8 30/01
21

Eu sei que estou atrasado para a festa ..

Pessoalmente, gosto da solução em: - http://www.dostips.com/DtTipsStringManipulation.php#Snippets.Replace

Também usamos extensivamente a função Dedupe para nos ajudar a enviar aproximadamente 500 e-mails diariamente via SMTP a partir de: - https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/sj8IUhMOq6o

e ambos funcionam nativamente sem a necessidade de ferramentas ou utilitários extras.

REPLACER:

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

DEDUPLICATOR (observe o uso de -9 para um número 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

Obrigado!

Leptonator
fonte
o script em lote não faz nada além de uma mera cópia de arquivo - também: por que você está agradecendo a si mesmo?
specializt
A solicitação original era substituir "FOO" por "BAR" em um arquivo de texto usando um script em lotes e, de preferência, com funções internas. Se alguma coisa eu estava agradecendo a postagem dos Grupos do Google, achei o que é fantástico e ainda a usamos até hoje. Além disso, veja postagens e respostas como essas sendo úteis para os usuários que estão no caminho também. Não vejo o seu comentário sobre a cópia do arquivo. Claro, ele pega o conteúdo de um arquivo e faz eco do resultado em outro arquivo, mas com base nos dados, ele apara e analisa as informações necessárias. Eu recomendaria experimentá-lo primeiro. ;)
Leptonator
é basicamente uma ferramenta de cópia de arquivo que substitui duas seqüências estáticas - você poderia pelo menos colocar duas variáveis ​​lá para que as pessoas que querem experimentá-la não precisem entender a sintaxe para poder usá-la - também: suposições pela internet quase sempre estão completamente erradas. Lembre-se disso.
specializt
4
@specializt - Por favor ... não estou aqui para debater semântica. Se você preferir, podemos colocar isso offline na sala de bate-papo.
Leptonator
2
Na minha opinião, esta é a resposta para a pergunta original. Usarei esta dica para configurar arquivos de inicialização para um serviço durante a instalação e não gostaria de ativar o PowerShell ou permitir que o mecanismo de script seja executado nos meus servidores. Com frequência, as respostas às perguntas relacionadas ao Windows começam com "instalar este dispositivo a partir daí", pois ainda existe uma atitude de "PC".
Mico
15

Quando você trabalha com o Git no Windows , basta iniciar git-bash e usar sed. Ou, ao usar o Windows 10, inicie "Bash no Ubuntu no Windows" (no subsistema Linux) e usesed .

É um editor de fluxo, mas pode editar arquivos diretamente usando o seguinte comando:

sed -i -e 's/foo/bar/g' filename
  • -i A opção é usada para editar no local no nome do arquivo.
  • -e A opção indica um comando para executar.
    • sé usado para substituir a expressão encontrada "foo" por "bar" e gé usado para substituir quaisquer correspondências encontradas.

Nota de ereOn:

Se você deseja substituir uma string nos arquivos com versão somente de um repositório Git, convém usar:

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

que faz maravilhas.

Jens A. Koch
fonte
1
Observe que, se você realmente está renomeando em um repositório git e deseja apenas substituir em arquivos com versão, você pode fazer: o git ls-files <eventual subfolders & filters> | xargs sed -i -e 's/foo/bar/g'que faz maravilhas.
ereOn
13

Eu brinquei com algumas das respostas existentes aqui e prefiro minha solução aprimorada ...

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

ou se você quiser salvar a saída novamente em um arquivo ...

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

A vantagem disso é que você pode canalizar a saída de qualquer programa. Também analisará o uso de expressões regulares com isso. Não foi possível descobrir como transformá-lo em um arquivo BAT para facilitar o uso ... :-(

Simon East
fonte
3
Esta é uma boa solução. Infelizmente, usar typesignifica que todas as linhas com mais de 80 caracteres são quebradas. Que dor.
Sirdank
12

Eu usei perl, e isso funciona maravilhosamente.

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

.orig é a extensão que seria anexada ao arquivo original

Para vários arquivos correspondentes, como * .html

for %x in (<filePattern>) do perl -pi.orig -e "s/<textToReplace>/<textToReplaceWith>/g;" %x
Faisal
fonte
Esta é a solução mais simples +1, ao converter de sh o bastão, basta substituir sedcom perl -pi.backup -ee apreciá-lo :)
Yann39
11

Com o replaceer.bat

1) Com a e?opção que avaliará seqüências de caracteres especiais, como \n\rsequências unicode. Nesse caso, substituirá o citado "Foo"e "Bar":

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

2) Substituir diretamente onde Fooe Barnão são citados.

call replacer.bat "C:\content.txt" "Foo" "Bar"
npocmaka
fonte
Não está funcionando para mim. Como você executa isso? Estou recebendo o erro 'replace_in_config.bat' não é reconhecido como um comando interno ou externo, programa operável ou arquivo em lote.
precisa saber é o seguinte
@FrenkyB - ele precisa estar no mesmo diretório onde você chamá-lo ou no caminho - ss64.com/nt/path.html
npocmaka
Eu tive todos os três arquivos no mesmo diretório.
precisa saber é o seguinte
9

Aqui está uma solução que eu achei que funcionou no Win XP. No meu arquivo em lotes em execução, incluí o seguinte:

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

O replace.batarquivo é como abaixo. Não encontrei uma maneira de incluir essa função no mesmo arquivo em lotes, porque a %%avariável sempre parece fornecer o último valor no loop 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
Chade
fonte
1
Infelizmente, isso também pula linhas em branco. Um recurso do comando {{for}}.
John Rocha
7

Dê uma olhada em Existe algum utilitário sed como para o cmd.exe que solicitou um equivalente sed no Windows, também deve se aplicar a esta pergunta. Sumário executivo:

  • Isso pode ser feito em arquivo em lote, mas não é bonito
  • Muitos executáveis ​​de terceiros disponíveis que farão isso por você, se você tiver o luxo de instalar ou simplesmente copiar um exe
  • Pode ser feito com VBScript ou similar, se você precisar de algo capaz de executar em uma caixa do Windows sem modificações, etc.
Jay
fonte
4

Pode ser um pouco tarde, mas frequentemente procuro coisas semelhantes, pois não quero passar pela dor de obter a aprovação de um software.

No entanto, você geralmente usa a instrução FOR de várias formas. Alguém criou um arquivo em lotes útil que faz uma pesquisa e substitui. Dê uma olhada aqui . É importante entender as limitações do arquivo em lotes fornecido. Por esse motivo, não copio o código fonte nesta resposta.

Peter Schuetze
fonte
4

Dois arquivos em lotes que fornecem search and replacefunções foram gravados pelos membros do Stack Overflow dbenhame aaciniusados native built-in jscriptno Windows.

Eles são ambos robuste very swift with large filesem comparação com scripting batch simples, e também simplerusar para substituir básica de texto. Ambos têm Windows regular expressioncorrespondência de padrões.

  1. Esse sed-likearquivo de lote auxiliar é chamado repl.bat(por dbenham).

    Exemplo usando a Lopção literal:

    echo This is FOO here|repl "FOO" "BAR" L
    echo and with a file:
    type "file.txt" |repl "FOO" "BAR" L >"newfile.txt"
    
  2. Esse grep-likearquivo em lotes auxiliar é chamado findrepl.bat(por aacini).

    Exemplo que possui expressões regulares ativas:

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

Ambos se tornam poderosos utilitários para todo o sistema when placed in a folder that is on the pathou podem ser usados ​​na mesma pasta com um arquivo em lotes ou no prompt do cmd.

Ambos têm case-insensitiveinterruptores e também muitas outras funções.

foxidrive
fonte
3

O comando Power Shell funciona como um encanto

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

Acabei de enfrentar um problema semelhante - "Pesquise e substitua texto dentro de arquivos", mas com a exceção de que tanto para nomes de arquivos quanto para busca / repalce, preciso usar regex. Como não estou familiarizado com o Powershell e quero salvar minhas pesquisas para uso posterior, preciso de algo mais "amigável" (preferível se tiver GUI).

Então, enquanto pesquisava no Google :), encontrei uma ótima ferramenta - FAR (Localizar e substituir) (não FART).

Esse pequeno programa possui uma interface gráfica agradável e suporta regex para pesquisar nomes de arquivos e arquivos. A única desvantagem é que, se você quiser salvar suas configurações, precisará executar o programa como administrador (pelo menos no Win7).

madcorp
fonte
É a mesma resposta que a resposta a partir de 2010 @VonC Neste tópico
jeb
@ jeb apontei que FAR não é FART - dois programas diferentes com nomes quase idênticos. O FAR possui GUI e pode trabalhar com regex, enquanto nos comentários abaixo desse tópico as pessoas mencionam que o FART não suporta regex.
Madcorp #
3

Estou preferem o uso sedde utilitários GNU para Win32 , o seguinte precisa ser notado

  • aspas simples ''não funcionará no Windows, use em ""vez disso
  • sed -inão funcionará no Windows, precisará de troca de arquivos

Portanto, o código de trabalho sedpara encontrar e substituir o texto em um arquivo no Windows é o seguinte:

sed -e "s/foo/bar/g" test.txt > tmp.txt && mv tmp.txt test.txt
Chetabahana
fonte
2
Antes que os usuários do Windows façam a troca de arquivos imediatamente: as versões mais recentes do sed suportam a edição no local -i! Se a sua versão sed funcionar, verifique o comando desta resposta: stackoverflow.com/a/33762001/2492801 .
Benjamin Bihler 26/08/19
2

Isso é algo que o script em lote simplesmente não faz bem.

O script ao qual os morechilli vinculados funcionarão para alguns arquivos, mas infelizmente serão bloqueados por outros que contenham caracteres como pipes ee comercial.

O VBScript é uma ferramenta interna melhor para esta tarefa. Consulte este artigo para um exemplo: http://www.microsoft.com/technet/scriptcenter/resources/qanda/feb05/hey0208.mspx


fonte
2

A Rachel deu uma excelente resposta, mas aqui está uma variação para ler o conteúdo de uma $datavariável do PowerShell . Você pode manipular facilmente o conteúdo várias vezes antes de gravar em um arquivo de saída. Veja também como os valores de várias linhas são fornecidos em arquivos em lote .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%"
Quem eu
fonte
2

Use o powershell em .bat - para Windows 7 ou superior

codificar utf8 é opcional, bom para sites

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

Baixar Cygwin (gratuito) e use comandos do tipo unix na linha de comando do Windows.

Sua melhor aposta: sed

jm.
fonte
10
Cygwin é mau. Não instale. Melhor usar o UnixUtils mencionado abaixo.
Zedoo 20/10/10
24
O que há de tão mau nisso?
jm.
@jm Pode ser porque você precisa instalar a coisa toda juntos, em vez de usar um único executável sempre que quiser.
Andry
Melhor usar o PowerShell, ele é realmente incorporado no Windows.
Preza8 30/01
0

Também pode ver as ferramentas Substituir e ReplaceFilter em https://zoomicon.github.io/tranXform/ (fonte incluída). O segundo é um filtro.

A ferramenta que substitui as strings nos arquivos está no VBScript (é necessário que o Windows Script Host [WSH] seja executado em versões antigas do Windows)

O filtro provavelmente não está funcionando com Unicode, a menos que você recompile com o Delphi mais recente (ou com o FreePascal / Lazarus)

George Birbilis
fonte
-5

Eu já enfrentei esse problema várias vezes ao codificar no Visual C ++. Se você o possui, pode usar o Utilitário Localizar e Substituir do Visual studio. Ele permite que você selecione uma pasta e substitua o conteúdo de qualquer arquivo nessa pasta por qualquer outro texto que desejar.

No Visual Studio: Editar -> Localizar e substituir Na caixa de diálogo aberta, selecione sua pasta e preencha as caixas "Localizar" e "Substituir por". Espero que isso seja útil.

Nadjib
fonte
2
Nadjib, sua resposta não ajuda o usuário porque você assume que eles estão usando um software do qual não fazem menção. Por favor, sugira uma opção que não requer software.
Aibrean
@ Aibrean a resposta é inútil, mas não por esse motivo, é o ponto de entrada que está errado.
Paulo