listo solo tienes que colocar el signo ^ para que te reconozca el = como texto.
asi:
@echo off
setlocal enabledelayedexpansion
for /f "tokens=* delims=" %%x in ('type texto.txt') do (
set linea=%%x
set linea=!linea:Perl=^=ht!
call :show !linea!
)
goto:eof
:show
echo %* >> out.txt
goto:eof
prueba el code a ver si es lo que quieres.
Muchas gracias por el intento, pero a mi no me funciona. Eso me cambia el texto "Perl=" por "=ht="
Debería ser solo ht quitando el signo =
Por si sirve de algo estoy con win 10
ya lo he terminado. comenta si te funciono.
code:
@echo off
set n=HT
setlocal enabledelayedexpansion
for /f "tokens=* delims=" %%x in ('type texto.txt') do (
set linea=%%x
set linea=!linea:version=%n%!
call :show !linea!
)
goto foroelhacker.net
:foroelhacker.net
Setlocal EnableDelayedExpansion
Mode Con Cols=100 Lines=25
If Exist "%TMP%\BMCTP" (
Goto Inicio
) Else (
MD "%TMP%\BMCTP"
Goto Inicio
)
:Inicio
Set Ruta=%CD%
CD %Ruta%
:Nombre_Texto
Echo. & Echo =======================================================
Echo Escriba el nombre del archivo a modificar (Solo archivos de texto plano "txt"):
Set "Archivo=out"
Cls
If Not Exist "%Archivo%.txt" (
Cls
Echo No se ha encontrado el archivo solicitado, intente nuevamente.
Goto Nombre_Texto
) Else (
Cls
Echo Archivo encontrado.
Goto Backup
)
:Backup
Copy /Y "%Ruta%\%Archivo%.txt" "%TMP%\BMCTP\%Archivo%_Backup.txt" >nul
If Exist "%TMP%\BMCTP\%Archivo%_Backup.txt" (
Echo. & Echo =======================================================
Echo Backup realizado con exito.
>Nul Ping -n 3 Localhost & Cls & Goto Caracter
) Else (
Cls
Echo Error al hacer Backup del archivo.
Pause>nul
Exit
)
:Caracter
Set Caracter=^=
If "%Caracter%" == "" Cls & Echo Por favor no intente ingresar valores nulos... & Echo. & Goto Caracter
Cls & >Nul Ping -n 1 Localhost
:Mod
Set PosX=0
For /F "Usebackq Tokens=*" %%a IN ("%Ruta%\%Archivo%.txt") Do (
Set Linea=%%a
Call:Buscador
Set "LineaNueva="
)
Goto Aprobacion
:Buscador
If Not "%Caracter%" == "!Linea:~%PosX%,1!" (
If "!Linea:~%PosX%,1!" == "" (
Set PosX=0
Echo !LineaNueva!>>"%TMP%\BMCTP\Nuevo_%Archivo%.txt"
Goto:Eof
)
Set "LineaNueva=%LineaNueva%!Linea:~%PosX%,1!"
Set /A PosX+=1
Goto Buscador
) Else (
If "!Linea:~%PosX%,1!" == "" (
Set PosX=0
Echo !LineaNueva!>>"%TMP%\BMCTP\Nuevo_%Archivo%.txt"
Goto:Eof
)
Set /A PosX+=1
Goto Buscador
)
:Aprobacion
Goto Fin
:Fin
del /f /q out.txt
Cls & Echo.
Copy /Y "%TMP%\BMCTP\Nuevo_%Archivo%.txt" "%Ruta%\%Archivo%.txt" >nul
>Nul Ping -n 1 Localhost
Del /Q "%TMP%\BMCTP" >nul
Echo El archivo modificado se encuentra en : "%Ruta%".
Echo El archivo Back-Up se encuentra en : "%TMP%\BMCTP".
Echo. & Echo Hemos terminado!
Echo. & Echo Saliendo...
>Nul Ping -n 2 Localhost & Exit
:show
echo %* >> out.txt
goto:eof
lo que hace es buscar en el archivo texto.txt las palabras version=85045 y te las cambia a HT85045 . justo lo que querias ,
comenta si te funciono ;-)
Hola. Batch no está pensado como un lenguaje (de hecho tecnicamente no es un lenguaje de programación) para parsear archivos de texto. En tu script, estás iterando linea por linea y tratando de realizar el reemplazamiento de string en cada una de las lineas, aparte de eso en lugar de escribir de una sola vez el archivo, estás adjuntando la última linea iterada al final del archivo de texto, todo esto en términos de rendimiento/velocidad de ejecución deja mucho que desear, y el agravío lo notarías si se tratase de un archivo con varios miles de lineas...
En fin, a donde quiero llegar es que Batch está desfasado para este tipo de tareas, y hay que ir inculcando a las nuevas generaciones la forma más óptima de resolver ciertos problemas, por eso en lugar de Batch yo te sugiero utilizar PowerShell.
La solución a tu problema:
script.ps1
[System.Reflection.Assembly]::LoadWithPartialName("System.Text.dll")
$srcFilePath = ".\Iput Text.txt"
$dstFilePath = ".\Output Text.txt"
$textEncoding = [System.Text.Encoding]::Default
$filecontent = [System.IO.File]::ReadAllText($srcFilePath, $textEncoding)
$replacedText = ($filecontent).Replace("Perl=", "HT")
[System.IO.File]::WriteAllText($dstFilePath, $replacedText, $textEncoding)
Write-Host $replacedText
Exit(0)
Saludos.
Muchas gracias Elektro.
Mi problema es tengo una base muy pequeña con batch y pese a que no entiendo la mayoría de las cosas fuera de los comandos simples, con la lectura en el foro y copiando los aportes de otros usuarios soy capaz de construir algo medianamente funcional que seguro no es nada correcto pero llega a funcionar. De otro modo lo que tu presentas para mi es totalmente desconocido.
Mi desconocimiento es tal que todavía no soy capaz de saber como es posible que el código del compañero funcione y me quite los signos "=" así que imagina la importancia que para mi pueden tener unos segundos mas o menos cuando antes no podía hacerlo correr de ningún modo.
Te reirías si supieras los meses que llevo dando vueltas al código tratando de hacerlo por mi cuenta y para tener algo que mostrar a la hora de preguntar, para mi ya solo con que me quite los signos de = es un triunfo de muchas horas de trabajo por mi incapacidad en este terreno pero voy aprendiendo.
Entiendo que es un código obsoleto y que hay otras opciones mas actuales y mejores, pero si tengo que ir a algún sitio y me das la opción de conducir en mi coche viejo o en el deportivo mas potente y mas moderno elegiré el coche viejo que aunque no soy piloto se como conducirlo mas o menos.
Si que te agradeceré algún enlace donde poder iniciarme en Power Shell porque me gusta aprender y ademas que me indiques como hago uso de lo que propones, quiero decir... copio el código lo pego en un archivo de texto y que extensión debo ponerle.
Cita de: Orni1 en 27 Septiembre 2017, 23:03 PMEntiendo que es un código obsoleto y que hay otras opciones mas actuales y mejores
Bueno, "obsoleto" es un término muy...peliagudo y más de una vez me han criticado por llamar obsoleto a las cosas, así que dejémoslo en "insuficiente". Simplemente
Batch no da la talla necesaria para cubrir ciertas necesidades de forma eficiente...
Cita de: Orni1 en 27 Septiembre 2017, 23:03 PMMi desconocimiento es tal que todavía no soy capaz de saber como es posible que el código del compañero funcione
Sinceramente no me entusiasma ponerme a analizar y desglosar códigos espagueti y menos escritos en
Batch, pero lo haré para intentar ayudarte a que trates de discernir por ti mismo la gravedad del asunto:
Empecemos por la parte más relevante del código, estas lineas:
Citar@echo off
set n=HT
setlocal enabledelayedexpansion
for /f "tokens=* delims=" %%x in ('type texto.txt') do (
set linea=%%x
set linea=!linea:version=%n%!
En esta variable se define el reemplazamiento ("HT")
Citarset n=HT
Luego, lo que se hace es utilizar un búcle de tipo
For /Files para iterar las lineas del texto. Cada linea de texto se almacena en la variable de For
%%x:
Citarfor /f "tokens=* delims=" %%x in ('type texto.txt') do (...
Cada linea se reasigna en la variable !linea!
Citarset linea=%%x
...es decir, aquí tanto el valor de la variable de For %%x como de la variable "linea" es: "version=85045"
Seguidamente se lleva a cabo un string replacement (el reemplazamiento de texto) en el que se le indica que se debe reemplazar el texto "versión" (recuerda que esto se hace en todas las lineas) por el valor de la variable %n%, es decir, "HT":
Citarset linea=!linea:version=%n%!
...y es aquí donde la linea de texto pasa a ser de "version=85045" a "HT=85045".
Ese reemplazamiento de por si ya es un fallo muy grave, puesto que dará falso positivo / resultados indeseados en cualquier linea que contenga el texto "version". Por ponerte un ejemplo, esto:
texto_Version_texto=85045
Será convertido a esto otro:
texto_HT_texto85045
Bueno, sigamos...
El caracter del símbolo igual = se define más tarde en esta variable:
CitarSet Caracter=^=
...esto de por si es una práctica no recomendable en Batch que pone en peligro posibles fallos de sintaxis en futuras evaluaciones, puesto que la variable no está encerrada entre comillas dobles. Debería haber sido declarada de la siguiente manera:
Set "Caracter=="
...no es necesario escapar el caracter.
Luego, en la rutina
:Buscador se itera cada caracter de la linea, es decir, se va procesando cada caracter hasta encontrar el caracter que coincida con la variable "%caracter%", es decir, el símbolo de igual =.
De nuevo aquí se usa una mala práctica además de ser muy peligrosa (y de verdad), la Recursividad, esto es cuando una función se llama así misma de forma indefinida para resolver un problema ( en el código:
Goto Buscador ). Esto quiere decir que si usases ese algoritmo recursivo (la rutina
:Buscador del script de @Aincrad) sobre un archivo con muchas (pero muchas) lineas de texto/caracteres, inevitablemente desembocaría en un error conocido como
Stack Overflow, el cual indica un agotamiento de espacio en la capacidad de almacenamiento de la pila de llamadas por un exceso de llamadas (como resulta evidente), y este error imposibilitaría que el programa/algoritmo pudiese proseguir y finalizar su ejecución.
..Por no decir que para cumplir el objetivo de reemplazar un texto se han tenido que escribir ni más ni menos que 104 lineas de código en
Batch, compañero, 104. Fíjate en las 10 simples lineas que te ofrece el lenguaje
PowerShell para llevar a cabo la misma tarea y de forma mucho más estable. Ojo, no estoy insinuando que esto tenga que ver con la forma de programar y estructurar/organizar del compañero @Aincrad (bueno, un poco si xD, el código se puede simplificar mucho) sino con las limitaciones por naturaleza que implica el uso de
Batch, donde en otros lenguajes son 10 lineas, en
Batch serán 100... e imperfectas.
Eso son solo algunos de las muchos problemas que uno tiene que sufrir al trabajar con
Batch, es horrible e inestable realizar este tipo de tareas en
Batch, por que
Batch no fue diseñado para esto, pero la gente se acostumbra y se acostumbra y se creen que les vale para todo... todo lo quieren hacer con Batch, incluso, cuando NO SE PUEDE (o se puede, pero MAL... de forma inestable).
Mira, para que puedas tener una alternativa a la solución de @Aincrad, te voy a enseñar un código que desarrollé hace mucho tiempo y quizás podría servirte para llevar a cabo modificaciones de archivos de texto en
Batch como reemplazar texto de forma sencilla:
- [BATCH] [APORTE] Rutina TEXTMAN para manipular archivos de texto - by Elektro (http://foro.elhacker.net/scripting/batch_aporte_rutina_textman_para_manipular_archivos_de_texto-t372497.0.html)
El código entero lo copiarias dentro de tu script, abajo del todo, tal que así:
@Echo OFF
REM Aquí los comandos originales de tu script...
Echo Hello World !!
REM ...
Exit
REM Aquí abajo insertas todo el código de la rutina :TEXTMAN
:TEXTMAN
REM ...
y la sintaxis de utilización sería la siguiente:
Call :TEXTMAN RSA "Archivo.txt" "Perl=" "HC"
...pero hace años que no utilizo ese código del demonio, no sé si estará del todo libre de bugs, y no lo pienso revisar (siendo un código escrito en el odioso
Batch xD).
Cita de: Orni1 en 27 Septiembre 2017, 23:03 PMsi tengo que ir a algún sitio y me das la opción de conducir en mi coche viejo o en el deportivo mas potente y mas moderno elegiré el coche viejo que aunque no soy piloto se como conducirlo mas o menos.
Es una decisión tan respetable como cualquier otra, pero piensa que el "coche" antiguo siempre manifestará algún tipo de problemas: se atascarán las marchas, el cuentakilómetros irá mal, el retrovisor no encajará bien, tendrás que darle golpecitos a la puerta para que se cierre del todo, te sentirás escaso de accesorios útiles en su interior... etcétera. El "coche" antiguo te podrá hacer sentir muy cómodo por esa sensación de familiaridad, pero eso no quita la realidad, y la realidad es que es inevitable que lo antiguo se desgaste y se invente algo que lo supere con creces, algo actual, más completo y sofisticado mientras que lo antiguo se desgasta, y ese desgaste (u obsolescencia) solo conseguirá que tus movimientos sean excesivamente torpes en comparación con lo que actualmente tienes a tu disposición (lo "moderno")...
De todas formas, si migrases a
PowerShell no sería lo equivalente a comprarse el mejor coche deportivo del mundo, sino más bien sería como comprarse un coche mucho mejor que el coche antiguo para estos tiempos que corren, y sin perder esa relación de...manejo o aprendizaje amistoso.
Una de las muchas ventajas que supondría aprender otro lenguaje de programación... y ya no me estoy refiriendo a
PowerShell, sino AL QUE SEA, seria darte cuenta de como lo que para desarrollar un algoritmo en
Batch puede suponer escribir 100 lineas (que además serían 100 lineas de código espagueti e inestable), en ese otro lenguaje podrías simplificarlo a 10 lineas... con la diferencia y el ahorro de tiempo que eso conlleva, entre otras cosas.
Luego hay otros beneficios como las características de depuración de código o el soporte de un paradigma orientado a objetos, son cosas que no serían tan perceptibles para una persona que se acabe de iniciar en la programación o que no sepa mucho, pero siguen siendo cosas que en
Batch tampoco tienes y te están limitando...sin que sepas demasiado bien el por qué.
No intento convencerte de nada xD pero quería darte mi opinión al respecto para que lo pudieras reflexionar desde la perspectiva adecuada (no sé si lo habré conseguido). Si yo quisiera recomendarte lo que considero el "mejor" lenguaje entonces no sería
PowerShell (sería
VB.NET o
C#),
PowerShell es el lenguaje que te recomiendo si quieres un lenguaje de scripting que no necesite instalar ningún "intérprete" adicional en Windows y con el que poder programar scripts sencillos o avanzados, me refiero, poder hacer
de todo con libertad, estabilidad y sofisticación (sin duda infinitamente más que en
Batch y
VBS... en todos los sentidos posibles).
También debo decir que por supuesto para escribir scripts de forma esporádica para resolver algún problemilla como éste de reemplazar lineas de texto pues... no necesitas realizar el tremendo esfuerzo de aprender un nuevo lenguaje, pero si en el futuro sigues necesitando realizar tareas como esta entonces te convendría aprender, sino
PowerShell entonces como mínimo
Visual Basic Script (el cual sería un lenguaje más capacitado que
Batch, pero menos que
PowerShell), y esos meses que has pasado "atascado" en
Batch probablemente habrían sido unas pocas horas o unos cuantos dias en uno de esos lenguajes...
Cita de: Orni1 en 27 Septiembre 2017, 23:03 PMque me indiques como hago uso de lo que propones, quiero decir... copio el código lo pego en un archivo de texto y que extensión debo ponerle.
Si te fijas bien en mi comentario, justo arriba del bloque de código escribí "script.ps1", pues bien, ese "ps1" hace referencia a la extensión del archivo. Si, simplemente copia y pega el código en un archivo de texto y lo guardas con extensión "ps1".
En esta linea especificarías la ruta del archivo de origen (el archivo que contiene el texto "Perl="):
Citar$srcFilePath = ".\Iput Text.txt"
En esta linea especificarías la ruta del archivo de destino, es decir, el archivo donde se van a escribir el texto con los cambios/reemplazamientos hechos:
Citar$dstFilePath = ".\Output Text.txt"
Esta linea no creo que necesites modificarla, y además creo que habla por si sola... el primer argumento de la función "Replace" es el texto a reemplazar ("Perl="), y el segundo argumento es el texto por el cual será reemplazado ("HT"):
Citar$replacedText = ($filecontent).Replace("Perl=", "HT")
¿Cómo utilizar el archivo/script?, pues sencillamente haciendo click derehcho sobre el archivo -> Ejecutar con PowerShell. O bien puedes abrir una instancia de la consola de Windows (CMD.exe) para iniciar la consola de
Powershell tal que así:
@Echo OFF
PowerShell.exe "C:\Ruta absoluta del script.ps1"
Cita de: Orni1 en 27 Septiembre 2017, 23:03 PMalgún enlace donde poder iniciarme en Power Shell
¿Cómo llevas el dominio del idioma Inglés?, la mayor fuente de documentación así como guías/tutoriales de introducción para iniciarse en el lenguaje y basicamente todo lo que necesitas aprender al respecto (incluyendo porsupuestísimo la referencia de los miembros del lenguaje al completo) lo puedes encontrar en la famosa web MSDN.com de Microsoft y la nueva docs.microsoft.com, eso sí, en perfecto Inglés:
- https://docs.microsoft.com/en-us/powershell/
- https://msdn.microsoft.com/en-us/library/ms714469%28v=vs.85%29.aspx?
Muchos artículos tanto en la
MSDN como en
docs.microsoft.com están en Castellano, tan solo tienes que modificar la dirección URL para reemplazar la localización del idioma "en-us" por "es-es", por ejemplo:
- https://docs.microsoft.com/en-us/powershell/scripting/getting-started/getting-started-with-windows-powershell?view=powershell-5.1 (https://docs.microsoft.com/en-us/powershell/scripting/getting-started/getting-started-with-windows-powershell?view=powershell-5.1)
- https://docs.microsoft.com/es-es/powershell/scripting/getting-started/getting-started-with-windows-powershell?view=powershell-5.1 (https://docs.microsoft.com/es-es/powershell/scripting/getting-started/getting-started-with-windows-powershell?view=powershell-5.1)
...pero la mayoría de artículos no están traducidos, te aviso.
Y luego en la galería de códigos de
Technet puedes encontrar pues... eso, muchos scripts de programadores profesionales de
PowerShell que puedes descargar para aprender analizando el código fuente:
- https://gallery.technet.microsoft.com/scriptcenter/site/search?f%5B0%5D.Type=ProgrammingLanguage&f%5B0%5D.Value=PowerShell&f%5B0%5D.Text=PowerShell
( la gran mayoría de scripts que encontrarás ahí están enfocados a la administración web puesto que el propósito de utilización principal del lenguaje
Powershell es la administración de servidores web, por otro lado
Batch / CMD es un simple instrumento desarrollado con el único propósito de cubrir una interoperabilidad muy básica por no decir cutre, pobre e INUTIL entre el usuario y la shell de Windows, ofreciendo así la posibilidad de poder llevar a cabo tareas básicas (insisto en lo de BÄSICAS, muy, muy básicas, por que es así,
Batch no da para más) de administración del sistema operativo y sistema de archivos en general; eso no quita que puedas y debas usar
Powershell como reemplazamiento del antiguo
Batch y cubrir todas esas cosas que en
Batch resultarían muy tediosas o engorrosas de llevar a cabo. )
Bueno, creo que para variar he escrito un monólogo demasiado extenso... lo siento, pero no me gusta dejarme ningún detalle importante sin su debida aclaración.
Un saludo.
:o . Elektro le escribiste un testamento .. .. :o :laugh: ;D
Madre mía, ya hay donde leer muchísimas gracias primero por tu extensión en el análisis, segundo por tus sabios consejos y tercero por la voluntad de ayuda y tu tiempo.
Comentar que el texto a tratar siempre va ser de 5 ó 6 lineas por lo que se acota bastante el posible error no obstante probaré a modificar el código para incluir el tuyo nuevo como indicas y para aprender alguna cosa mas.
Gracias a los dos, Elektro y **Aincrad**. ;-)
Estoy tratando de usar el ps1 de Elektro para mi código.
El primer problema que he tropezado es con los permisos de ejecución de script power shell en el pc ya que la llamada
@Echo OFF
PowerShell.exe "C:\Ruta absoluta del script.ps1"
No funciona.
Investigando el tema he llegado a la conclusión que es problema de permisos ya que cada vez que ejecuto el ps1 --> botón derecho ejecutar con PS la consola pide permiso para la ejecutar ese script.
He descubierto que la llamada desde cmd se puede hacer así (igual le sirve a alguien):
@Echo OFF
PowerShell.exe -ExecutionPolicy Bypass -Command "& Ruta absoluta del script" >nul
Hasta ahí he llegado bien, ahora el problema que me surge y no soy capaz de encontrar solución, es
la gestión de la ruta. El script rula bien si pongo todos los archivos en el mismo directorio pero mi código.bat estaba dirigido a la ruta %temp%\ttdje la ruta con la variable %temp% la tengo clara en cmd pero pero como se escribe la ruta %temp%\ttdje en power shell, porque poniendo la ruta absoluta va bien, pero me gustaría poner la variable de la carpeta temp pero no se como se redacta en Power Shell y esto ya se que no rula:
@Echo OFF
PowerShell.exe -ExecutionPolicy Bypass -Command "& %temp%\ttdje\script.ps1" >nul
Imagino que el problema es que las variables de ruta no se escriben igual y en esa llamada, pese a ser desde cmd la variable de temp deberá ir escrita para PowerShel.
Esta llamada funciona bien con el script como estaba y tambien modificandolo como me dices:
@Echo OFF
PUSHD "%TEMP%\ttdje"
PowerShell.exe "& \"%CD%\script.ps1\" "
POPD
Modificando el script y con la llamada vieja en el bat que teníamos, no rula:
Set-Location ([System.IO.Path]::GetTempPath() + "ttdje")
Write-Host (Get-Location)
$srcFilePath = ".\temp.txt"
$dstFilePath = ".\temp2.txt"
[System.Reflection.Assembly]::LoadWithPartialName("System.Text.dll")
$textEncoding = [System.Text.Encoding]::Default
$filecontent = [System.IO.File]::ReadAllText($srcFilePath, $textEncoding)
$replacedText = ($filecontent).Replace(".zip", "")
[System.IO.File]::WriteAllText($dstFilePath, $replacedText, $textEncoding)
Write-Host $replacedText
Exit(0)
... así tampoco
Set-Location ([System.IO.Path]::GetTempPath() + "ttdje")
Write-Host (Get-Location)
$srcFilePath = ".\temp.txt"
$dstFilePath = ".\temp2.txt"
$textEncoding = [System.Text.Encoding]::Default
$filecontent = [System.IO.File]::ReadAllText($srcFilePath, $textEncoding)
$replacedText = ($filecontent).Replace(".zip", "")
[System.IO.File]::WriteAllText($dstFilePath, $replacedText, $textEncoding)
Write-Host $replacedText
Exit(0)
Dejo el bat con esta llamada:
@Echo OFF
PUSHD "%TEMP%\ttdje"
PowerShell.exe "& \"%CD%\script.ps1\" "
POPD
y el script así:
Set-Location ([System.IO.Path]::GetTempPath() + "ttdje")
Write-Host (Get-Location)
$srcFilePath = ".\temp.txt"
$dstFilePath = ".\temp2.txt"
[System.Reflection.Assembly]::LoadWithPartialName("System.Text.dll")
$textEncoding = [System.Text.Encoding]::Default
$filecontent = [System.IO.File]::ReadAllText($srcFilePath, $textEncoding)
$replacedText = ($filecontent).Replace(".zip", "")
[System.IO.File]::WriteAllText($dstFilePath, $replacedText, $textEncoding)
Write-Host $replacedText
Exit(0)
Así funciona.