¿Cómo puede encontrar y reemplazar texto en un archivo usando el entorno de línea de comandos de Windows?


492

Estoy escribiendo una secuencia de comandos de archivo por lotes utilizando el entorno de línea de comandos de Windows y quiero cambiar cada aparición de algún texto en un archivo (ej. "FOO") con otro (ej. "BAR"). ¿Cuál es la forma más sencilla de hacer eso? ¿Alguna función incorporada?



use esto:echo(%text:%search%=%replace%%)
scientist_7

Respuestas:


308

Muchas de las respuestas aquí me ayudaron a orientarme en la dirección correcta, sin embargo, ninguna fue adecuada para mí, por lo que estoy publicando mi solución.

Tengo Windows 7, que viene con PowerShell incorporado. Aquí está el script que usé para buscar / reemplazar todas las instancias de texto en un archivo:

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

Para explicarlo:

  • powershell inicia powershell.exe, que se incluye en Windows 7
  • -Command "... " es un argumento de línea de comando para powershell.exe que contiene el comando para ejecutar
  • (gc myFile.txt)lee el contenido de myFile.txt( gces la abreviatura del Get-Contentcomando)
  • -replace 'foo', 'bar'simplemente ejecuta el comando reemplazar para reemplazar fooconbar
  • | Out-File myFile.txt canaliza la salida al archivo myFile.txt
  • -encoding ASCII evita la transcripción del archivo de salida a unicode, como señalan los comentarios

Powershell.exe ya debería ser parte de su declaración PATH, pero si no puede agregarla. La ubicación en mi máquina esC:\WINDOWS\system32\WindowsPowerShell\v1.0


71
Cuidado, este comando también puede transcodificar el archivo a codificación Unicode. Puede especificar manualmente la codificación mediante la adición -encoding ASCIIo la UTF8o lo que sea necesario. También tenga cuidado, si apunta a UTF8, puede introducir una marca de orden de bytes al comienzo del archivo que no apareció en el original.
Wyck

78
@Wyck Me tomó un tiempo averiguar dónde ponerlo -encoding ASCII. Para cualquiera que lo necesite en el futuro, seríaOut-File -encoding ASCII myFile.txt
rwilson04

15
Lo único que tuve que cambiar fue usar en Set-Contentlugar de Out-File.
kurtzmarc

66
Esto funciona, pero el rendimiento es terrible incluso en una breve lista de archivos.
jsuddsjr

23
Tenga en cuenta que el token de reemplazo ('foo' en este caso) se trata como una expresión regular. Si tiene caracteres especiales allí (tenía []), debe anteponerlos con una \ (barra invertida).
JW

183

Si está en la versión de Windows que admite .Net 2.0, reemplazaría su shell. PowerShell le brinda todo el poder de .Net desde la línea de comandos. También hay muchos comandos incluidos. El siguiente ejemplo resolverá su pregunta. Estoy usando los nombres completos de los comandos, hay alias más cortos, pero esto te da algo para Google.

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

10
Puedo ver que PowerShell es capaz de archivar esto. Pero, ¿cómo puedo hacer que esto se ejecute desde un archivo por lotes (ejemplo: myProc.bat)?
Pablo Venturino

3
@Pablo, use powershell.exe y ajuste el comando ps en un solo parámetro
lubos hasko

56
-1 .. Seguro que la respuesta fue aceptada, pero no es la respuesta a la pregunta especificada.
baash05

28
Esto fallará con un error de archivo en uso si guarda en el mismo archivo. Debe cambiar el comando powershell a: (Get-Content test.txt) | ForEach-Object {$ _ -replace "foo", "bar"} | Set-Content test.txt
BigMomma

66
Vea la respuesta de @Rachel:powershell -Command "(gc myFile.txt) -replace 'foo', 'bar' | sc myFile.txt"
Nigel Touch

161

Acabo de utilizar FART ( utilidad de línea de comandos " F ind A y R Eplace T ext"):
excelente software gratuito para la sustitución de texto dentro de un gran conjunto de archivos.

Los archivos de instalación están en SourceForge .

Ejemplo de uso:

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

previsualizará los reemplazos para hacer recursivamente en los archivos de esta distribución de Perl.

El único problema: el ícono del sitio web de FART no es exactamente de buen gusto, refinado o elegante;)


Actualización 2017 (7 años después) jagb señala en los comentarios al artículo de 2011 " FARTing the Easy Way - Find and Replace Text " de Mikail Tunç


19
Lo bueno es que es un solo exe. Sin dependencias No hay huellas pequeñas. Súper fácil de implementar.
Serge Wautier

2
Muy ligero y fácil de usar, pero esperaba que imprimiera los lugares exactos donde tuvieron lugar los reemplazos. No poder ver eso me dio una sensación de inseguridad.
William Niu

44
Gracias, es perfecto, debería ser parte de las herramientas estándar de dos y funcionó de maravilla. Sin embargo, la opción -p no muestra cuántos cambios "haría" y siempre informa 0, lo que me arrojó por unos minutos
sradforth

3
Entiendo que esta es una pregunta muy antigua, pero encontré más información y espero que sea útil para los usuarios de Stack Overflow. Solo otro enlace para FART donde el producto está bien explicado: FART explicado en @ emtunc.org y se puede encontrar otra página aquí: FART Tenga cuidado con el reemplazo de /y 'ya que esto no funciona para todos nosotros , para mí funcionó en algunos casos pero no funcionó en algunos archivos y no sé por qué. Utilicé esto para reemplazar el texto con otro texto y un/
jagb

44
@jagb Gracias. He incluido su enlace en la respuesta para mayor visibilidad.
VonC

128

Reemplazar - Reemplazar una subcadena con sustitución de cadena Descripción: Para reemplazar una subcadena con otra cadena, use la función de sustitución de cadena. El ejemplo que se muestra aquí reemplaza todas las ocurrencias de errores ortográficos "teh" con "the" en la variable de cadena str.

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

Salida de script:

teh cat in teh hat
the cat in the hat

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


30
¿Cómo es mejor la sugerencia sed? Esta parece ser la respuesta más simple de todas y no requiere instalar nada.
DonBecker

55
¿Se puede hacer algún tipo de coincidencia de patrones aquí? ¿Comodines, expresiones regulares, etc.?
keyo

27
"¿Cómo es mejor la sugerencia sed?" - sed y utilidades similares operan en archivos; este fragmento omite el paso importante de leer líneas del archivo de entrada y escribir en el archivo de salida, al tiempo que garantiza que los caracteres especiales en el archivo se manejen correctamente.
Joe

77
@Asad, sí, es cierto, el OP preguntaba por los archivos, pero de hecho funciona con transmisiones que no tienen que ser archivos. Pero mi punto aquí es que esta respuesta es errónea, ya que omite la lectura / escritura de una secuencia y el manejo de caracteres especiales.
Joe

44
@Bill, ¿cómo usar la variable como texto de reemplazo? es decir. Tengo valor en una variable y una cadena que tiene algo de delimitador. set str =% str: "##" =% varValue %% no funciona. ¿Alguna solución?
MalTec

55

Crear archivo 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 esta secuencia de comandos revisada (que llamaremos replace.vbs) simplemente escriba un comando similar a este desde el símbolo del sistema:

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


Esto es bueno, ¿permite el uso de RegEx?
user280109

3
@ user280109 Sí, admite VBScript RegExp. Puede usar esta opción para sustituir el uso de una expresión regular: With (New RegExp): strNewText = .Replace(strText, strOldText, strNewText): End With. Usted puede obtener el texto de los 9 primeros grupos de captura usando $1, $2... $9.
Cepillo de dientes

2
VBScript a menudo se pasa por alto (y se odia), pero está disponible en todas las plataformas de Windows, es muy legible y en realidad tiene capacidades muy potentes +1
zelanix

1
@ user280109 Acabas de dar el comando Lo que necesito. Pero quiero reemplazar (no distingue entre mayúsculas y minúsculas) ¿Puede proporcionar el comando para eso?
Ajmal Praveen

49

BatchSubstitute.baten dostips.com es un ejemplo de búsqueda y reemplazo utilizando un archivo por lotes puro.

Se utiliza una combinación de FOR, FINDyCALL SET .

Las líneas que contienen caracteres entre "&<>]|^pueden ser tratadas incorrectamente.



8
Tengo que cuestionar la utilidad de un sitio de fragmentos de código cuyos términos de uso prohíben copiar cualquier código ("No puede distribuir ninguna información proporcionada bajo el dominio dostips.com de ninguna forma sin el permiso expreso por escrito del propietario del dominio"). .
Gilles 'SO- deja de ser malvado'

1
Estoy de acuerdo en que sus términos son confusos, también dicen "La información proporcionada bajo el dominio dostips.com es útil", así que supongo que están contentos de que la gente copie el código para resolver un problema. No estoy seguro de que he leído alguna vez cualquiera de los términos y condiciones y estado feliz ...
morechilli

55
Esto es genial. Me encantan las respuestas que no implican descargar otra cosa para hacerlo.
Ruairi O'Brien

También me gustan las soluciones que no involucran utilidades externas, desafortunadamente, sigo obteniendo "find: predicado inválido ''" cuando intento ejecutar este lote. Realmente no tengo tiempo para depurarlo en este momento.
Jahmic

2
El error "buscar: predicado inválido ''" se debió a una utilidad externa "buscar" en mi sistema. Una vez eliminado, esto funcionó bien.
Jahmic

47

Nota : asegúrese de ver la actualización al final de esta respuesta para obtener un enlace al JREPL.BAT superior que reemplaza a REPL.BAT
JREPL.BAT 7.0 y versiones superiores de forma nativa compatible con Unicode (UTF-16LE) a través de la /UTFopción, así como cualquier otro conjunto de caracteres, incluido UTF-8, a través de ADO !!!!


He escrito una pequeña utilidad híbrida JScript / batch llamada REPL.BAT que es muy conveniente para modificar archivos ASCII (o ASCII extendido) a través de la línea de comando o un archivo por lotes. El script puramente nativo no requiere la instalación de ningún tercero ejecutable, y funciona en cualquier versión moderna de Windows desde XP en adelante. También es muy rápido, especialmente en comparación con las soluciones de lotes puros.

REPL.BAT simplemente lee stdin, realiza una búsqueda y reemplazo de expresiones regulares JScript y escribe el resultado en stdout.

Aquí hay un ejemplo trivial de cómo reemplazar foo con bar en test.txt, suponiendo que REPL.BAT está en su carpeta actual, o mejor aún, en algún lugar dentro de su RUTA:

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

Las capacidades de expresión regular de JScript lo hacen muy poderoso, especialmente la capacidad del texto de reemplazo para hacer referencia a subcadenas capturadas del texto de búsqueda.

He incluido una serie de opciones en la utilidad que la hacen bastante poderosa. Por ejemplo, la combinación de las opciones My Xpermite la modificación de archivos binarios. La Mopción de varias líneas permite búsquedas en varias líneas. La Xopción de patrón de sustitución extendido proporciona secuencias de escape que permiten la inclusión de cualquier valor binario en el texto de reemplazo.

Toda la utilidad podría haberse escrito como JScript puro, pero el archivo por lotes híbrido elimina la necesidad de especificar explícitamente CSCRIPT cada vez que desee utilizar la utilidad.

Aquí está el script REPL.BAT. La documentación completa está incrustada en el 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));
}


ACTUALIZACIÓN IMPORTANTE

He dejado de desarrollar REPL.BAT y lo he reemplazado con JREPL.BAT. Esta nueva utilidad tiene la misma funcionalidad de REPL.BAT, y mucho más:

  • Compatibilidad con Unicode UTF-16LE a través de las capacidades nativas de CSCRIPT unicode, y cualquier otro conjunto de caracteres (incluido UTF-8) a través de ADO.
  • Lea directamente / escriba directamente en un archivo: no necesita tuberías, redirección o comando de movimiento.
  • Incorporar JScript proporcionado por el usuario
  • Facilidad de traducción similar a unix tr, solo que también admite búsqueda de expresiones regulares y reemplazo de JScript
  • Descartar texto no coincidente
  • Prefijar líneas de salida con número de línea
  • y más...

Como siempre, la documentación completa está incrustada en el script.

La solución trivial original ahora es aún más simple:

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

La versión actual de JREPL.BAT está disponible en DosTips . Lea todas las publicaciones posteriores en el hilo para ver ejemplos de uso y un historial del desarrollo.


¡Buena cosa! Me encanta este b / c de la simplicidad y la forma en que puede adaptarlo a cualquier script, por lo tanto, escribir código JS que un lote malo.
Adaptabi

Editar: se agregó la opción A para imprimir solo las líneas que se han modificado. También se mejoró la opción X para admitir la \qrepresentación ", y los literales de búsqueda ahora admiten todas las secuencias de escape extendidas cuando se combinan las opciones L y X.
dbenham

@dbenham - +1. Este es un enfoque ingenioso, será útil para varias otras tareas también. Gracias por publicarlo.
bw

EDITAR: modifiqué el comportamiento de \ xnn cuando se usa la opción X para que el código represente el código de bytes ASCII extendido. También se agregó una opción de versión V /.
dbenham

99
@dbenham Esto es una joya. ¿Por qué no lo pones en GitHub o como Gist? Haría las versiones, seguimientos, lanzamientos / distribución, arreglos y más fácil. Si necesita ayuda con eso, hágamelo saber.
Atif Aziz

36

Use FNR

Usa la fnrutilidad. Tiene algunas ventajas sobre fart:

  • Expresiones regulares
  • GUI opcional Tiene un "botón Generar línea de comando" para crear texto de línea de comando para colocar en un archivo por lotes.
  • Patrones de líneas múltiples: la GUI le permite trabajar fácilmente con patrones de líneas múltiples. En FART tendrías que escapar manualmente de los saltos de línea.
  • Le permite seleccionar la codificación del archivo de texto. También tiene una opción de detección automática.

Descargue FNR aquí: http://findandreplace.io/?z=codeplex

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


1
Esto es bonito. Ser capaz de generar la línea de comando desde la interfaz gráfica de usuario es una característica simple y agradable que me puso en marcha rápidamente.
David Hammond

Herramienta muy útil. Intenté FART antes pero la documentación está desactualizada.
Artur Kędzior

Herramienta genial, incluso admite expresiones regulares. Esto es algo que le falta a FART.
Dio Phung

1
Gracias por indicar esta herramienta. Ejemplar único, gran reemplazo para FART que ya no se desarrolla (y pierde expresiones regulares); y la sintaxis de PowerShell es tan insoportable.
Gras Double

Esto es de lo más útil. Estaba buscando reemplazo grep + sed en windows, ¡esto funcionó muy bien!
Serban Tanasa

25

No creo que haya una manera de hacerlo con ningún comando incorporado. Te sugiero que descargues algo como Gnuwin32 o UnxUtils y uses el sedcomando (o solo descargar sed):

sed -c s/FOO/BAR/g filename

2
Use cygwin ( cygwin.com ). Es la siguiente mejor opción para instalar realmente Linux.
Andrew Johnson el

Es mejor si uno puede proporcionar una solución que no se base en instalar cygwin. La manipulación de cadenas POSIX es obvia: hacer esto en Windows es un poco más oscuro.
Rex

44
Gnuwin32 y UnxUtils son binarios independientes creados para Windows. No dependen de cygwin.
Ferruccio

1
cygwin: sed -i -b -e 's/FOO/BAR/g' `find . -name *.txt`-i - edita el archivo in situ; -b - no procese CR + LF - sin esta opción CR + LF se convertiría a LF
Alexey Vishentsev

@ AndrewJohnson La opinión y la información son dos cosas diferentes.
Preza8

21

Sé que llego tarde a la fiesta ...

Personalmente, me gusta la solución en: - http://www.dostips.com/DtTipsStringManipulation.php#Snippets.Replace

También, utilizamos ampliamente la función Dedupe para ayudarnos a entregar aproximadamente 500 correos electrónicos diariamente a través de SMTP desde: - https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/sj8IUhMOq6o

y ambos funcionan de forma nativa sin necesidad de herramientas o utilidades adicionales.

REEMPLAZO

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

DEDUPLICADOR (tenga en cuenta el uso de -9 para un 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

¡Gracias!


el script por lotes no hace más que una simple copia de archivo, también: ¿por qué te estás agradeciendo?
specializt

La solicitud original era reemplazar "FOO" con "BAR" en un archivo de texto usando un script por lotes y con funciones incorporadas preferiblemente. En todo caso, estaba agradeciendo la publicación de Grupos de Google que encontré que funciona de maravilla y todavía la usamos hasta el día de hoy. Además, vea las publicaciones y respuestas como estas que también son útiles para los usuarios que vienen en el futuro. No veo su comentario sobre la copia del archivo. Claro, toma el contenido de un archivo y hace eco del resultado en otro archivo, pero en función de los datos, recorta y analiza la información necesaria. Recomiendo probarlo primero. ;)
Leptonator

es básicamente una herramienta de copia de archivos que reemplaza dos cadenas estáticas; al menos podría haber colocado dos variables allí para que las personas que quieran probarlo no necesiten entender la sintaxis para poder usarla, también: Las suposiciones en Internet casi siempre son completamente erróneas. Recuerda eso.
specializt

44
@specializt - Por favor ... no estoy aquí para debatir la semántica. Si lo desea, ¿podemos desconectarlo a la sala de chat?
Leptonator

2
En mi opinión, esta es la respuesta a la pregunta original. Usaré este consejo para configurar los archivos de inicialización para un servicio durante la instalación, y no quisiera habilitar PowerShell ni permitir que el motor de secuencias de comandos se ejecute en mis servidores. A menudo, las respuestas a preguntas relacionadas con Windows comienzan con "instalar este artilugio desde allí", ya que todavía existe una actitud de "PC".
mico

15

Cuando trabaje con Git en Windows , simplemente inicie git-bash y use sed. O, cuando use Windows 10, inicie "Bash en Ubuntu en Windows" (desde el subsistema Linux) y utilícelo sed.

Es un editor de flujo, pero puede editar archivos directamente mediante el siguiente comando:

sed -i -e 's/foo/bar/g' filename
  • -i La opción se utiliza para editar en el lugar en el nombre del archivo.
  • -e La opción indica un comando para ejecutar.
    • sse usa para reemplazar la expresión encontrada "foo" con "bar" y gse usa para reemplazar las coincidencias encontradas.

Nota de ereOn:

Si desea reemplazar una cadena en archivos versionados solo de un repositorio Git, puede usar:

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

que hace maravillas


1
Tenga en cuenta que si realmente está haciendo ese cambio de nombre en un repositorio git y solo desea reemplazar en archivos versionados, es posible que desee hacer: lo git ls-files <eventual subfolders & filters> | xargs sed -i -e 's/foo/bar/g'que funciona de maravilla.
antes del

13

Jugué con algunas de las respuestas existentes aquí y prefiero mi solución mejorada ...

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

o si desea guardar la salida nuevamente en un archivo ...

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

El beneficio de esto es que puede canalizar la salida de cualquier programa. También investigará el uso de expresiones regulares con esto. No se pudo encontrar la forma de convertirlo en un archivo BAT para un uso más fácil ... :-(


3
Esta es una buena solución. Desafortunadamente, el uso typesignifica que todas las líneas de más de 80 caracteres quedan ajustadas. Que dolor.
sirdank

12

He usado perl, y eso funciona de maravilla.

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

.orig es la extensión que agregaría al archivo original

Para varios archivos que coinciden, como * .html

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

Esta es la solución más simple 1, al convertir de sh a batear, basta con sustituir sedcon perl -pi.backup -ey apreciar que :)
Yann39

11

Con el replacecer.bat

1) Con la e?opción que evaluará secuencias de caracteres especiales como \n\rsecuencias unicode. En este caso se sustituirá citado "Foo"y "Bar":

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

2) Sencillo sustitución donde el Fooy Barno se citan.

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

No está funcionando para mi. ¿Cómo ejecutas esto? Recibo el error 'replace_in_config.bat' no se reconoce como un comando interno o externo, programa operativo o archivo por lotes.
FrenkyB

@FrenkyB: debe estar en el mismo directorio donde lo llama o en la ruta - ss64.com/nt/path.html
npocmaka

He tenido los tres archivos en el mismo directorio.
FrenkyB

9

Aquí hay una solución que encontré que funcionó en Win XP. En mi archivo por lotes en ejecución, incluí lo siguiente:

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

El replace.batarchivo es el siguiente. No encontré una manera de incluir esa función dentro del mismo archivo por lotes, porque la %%avariable siempre parece dar el último valor en el bucle 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
Lamentablemente, esto también omite las líneas en blanco. Una característica del comando {{for}}.
John Rocha

7

Eche un vistazo a ¿Hay alguna utilidad sed like para cmd.exe que solicitó un equivalente sed en Windows? También debería aplicarse a esta pregunta. Resumen Ejecutivo:

  • Se puede hacer en archivo por lotes, pero no es bonito
  • Muchos ejecutables de terceros disponibles que lo harán por usted, si tiene el lujo de instalar o simplemente copiar un exe
  • Se puede hacer con VBScript o similar si necesita algo capaz de ejecutarse en un cuadro de Windows sin modificación, etc.

4

Puede llegar un poco tarde, pero con frecuencia estoy buscando cosas similares, ya que no quiero superar el dolor de obtener la aprobación del software.

Sin embargo, generalmente usa la declaración FOR en varias formas. Alguien creó un archivo por lotes útil que realiza una búsqueda y reemplazo. Echa un vistazo aquí . Es importante comprender las limitaciones del archivo por lotes proporcionado. Por esta razón, no copio el código fuente en esta respuesta.


4

search and replaceLos miembros de Stack Overflow han escrito dos archivos por lotes que proporcionan funciones dbenhamy aaciniutilizannative built-in jscript en Windows.

Ambos son robusty se very swift with large filescomparan con las secuencias de comandos por lotes simples, y también simplerpara usar para el reemplazo básico de texto. Ambos tienen Windows regular expressioncoincidencia de patrones.

  1. Este sed-likearchivo por lotes auxiliar se llamarepl.bat (por dbenham).

    Ejemplo usando el Linterruptor 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. Este grep-likearchivo por lotes auxiliar se llamafindrepl.bat (por aacini).

    Ejemplo que tiene expresiones regulares activas:

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

Ambos se convierten en poderosas utilidades de todo el sistema when placed in a folder that is on the path , o se pueden usar en la misma carpeta con un archivo por lotes, o desde el indicador de cmd.

Ambos tienen case-insensitiveinterruptores y también muchas otras funciones.


3

El comando Power Shell funciona de maravilla

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

3

Acabo de enfrentar un problema similar: "Buscar y reemplazar texto dentro de archivos", pero con la excepción de que tanto para los nombres de archivo como para buscar / reparar necesito usar expresiones regulares. Debido a que no estoy familiarizado con Powershell y quiero guardar mis búsquedas para un uso posterior, necesito algo más "fácil de usar" (preferible si tiene GUI).

Entonces, mientras buscaba en Google :) encontré una gran herramienta: FAR (Buscar y reemplazar) (no FART).

Ese pequeño programa tiene una GUI agradable y admite expresiones regulares para buscar en nombres de archivo y dentro de archivos. La única desventaja es que si desea guardar su configuración, debe ejecutar el programa como administrador (al menos en Win7).


Es la misma respuesta que la respuesta de 2010 @VonC En este hilo
jeb

@jeb Señalé que FAR no es FART : dos programas diferentes con nombres casi idénticos. FAR tiene GUI y puede trabajar con expresiones regulares, mientras que en los comentarios a continuación ese hilo la gente menciona que FART no admite expresiones regulares.
madcorp

3

Estoy prefiero uso sedde utilidades GNU para Win32 , las siguientes deben ser observado

  • la comilla simple ''no funcionará en Windows, use ""en su lugar
  • sed -ino funcionará en Windows, necesitará el intercambio de archivos

Entonces, el código de trabajo sedpara encontrar y reemplazar texto en un archivo en Windows es el siguiente

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

2
Antes de que los usuarios de Windows hagan el intercambio de archivos inmediatamente: ¡las versiones más nuevas de sed admiten la edición en el lugar con -i! Si su versión sed lo hace, verifique el comando de esta respuesta: stackoverflow.com/a/33762001/2492801 .
Benjamin Bihler

2

Esta es una cosa que las secuencias de comandos por lotes simplemente no funcionan bien.

El guión morechilli vinculado a funcionará para algunos archivos, pero desafortunadamente se ahogará con los que contienen caracteres como tuberías y símbolos de unión.

VBScript es una mejor herramienta integrada para esta tarea. Consulte este artículo para ver un ejemplo: http://www.microsoft.com/technet/scriptcenter/resources/qanda/feb05/hey0208.mspx


2

@Rachel dio una excelente respuesta, pero aquí hay una variación para leer contenido en una $datavariable de PowerShell . Luego, puede manipular fácilmente el contenido varias veces antes de escribir en un archivo de salida. También vea cómo se proporcionan valores de varias líneas en un archivo por lotes .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

Use powershell en .bat - para Windows 7+

codificar utf8 es opcional, bueno para sitios web

@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

Descargar Cygwin (gratis) y use comandos similares a Unix en la línea de comandos de Windows.

Tu mejor apuesta: sed


10
Cygwin es malvado. No lo instales. Mejor use UnixUtils mencionado a continuación.
zedoo

24
¿Qué tiene de malo?
jm.

@jm Puede deberse a que tiene que instalar todo junto en lugar de usar un solo ejecutable cuando lo desee.
Andry

Mejor usar powershell, en realidad está integrado en Windows.
Preza8

0

También puede ver las herramientas Reemplazar y Reemplazar filtro en https://zoomicon.github.io/tranXform/ (fuente incluida). El segundo es un filtro.

La herramienta que reemplaza las cadenas en los archivos está en VBScript (necesita Windows Script Host [WSH] para ejecutarse en versiones antiguas de Windows)

El filtro probablemente no funciona con Unicode a menos que recompile con el último Delphi (o con FreePascal / Lazarus)


-5

Me he enfrentado a este problema varias veces mientras codificaba bajo Visual C ++. Si lo tiene, puede usar la utilidad de búsqueda y reemplazo de Visual Studio. Le permite seleccionar una carpeta y reemplazar el contenido de cualquier archivo en esa carpeta con cualquier otro texto que desee.

En Visual Studio: Editar -> Buscar y reemplazar En el cuadro de diálogo abierto, seleccione su carpeta y complete los cuadros "Buscar qué" y "Reemplazar con". Esperamos que esto sea útil.


2
Nadjib, su respuesta no ayuda al usuario porque supone que está utilizando un software del que no hace mención. Sugiera una opción que no requiera software.
Aibrean

@Aibrean la respuesta es inútil, pero no por esa razón, es el punto de entrada lo que está mal.
Paul
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.