Пакетный файл: Как заменить "=" (знаки равенства) и строковую переменную? - PullRequest
5 голосов
/ 04 марта 2012

Помимо SED, как заменить знак равенства? И как я могу использовать строковую переменную при замене строки?

Рассмотрим этот пример:

For /F "tokens=*" %%B IN (test.txt) DO (
   SETLOCAL ENABLEDELAYEDEXPANSION
   SET t=is
   SET old=%%B
   SET new=!old:t=!
   ECHO !new!

   ENDLOCAL
)

:: SET new=!old:==!

Две проблемы:

Во-первых, я не могу использовать переменную% t% в!: =!.

   SET t=is
   SET old=%%B
   SET new=!old:t=!

Во-вторых, я не могу заменить знак равенства в командной строке

   SET new=!old:==!

Ответы [ 6 ]

3 голосов
/ 13 августа 2018

Я сам создал для этого простое решение, может, оно кому-нибудь поможет.

Недостаток (или преимущество зависит от того, что вы хотите сделать) состоит в том, что несколько знаков равенства один за другим обрабатываются как один знак равенства. (пример: «str == ing» выдает тот же вывод, что и «str = ing»)

@echo off
set "x=this is=an test="
echo x=%x%

call :replaceEqualSign in x with _
echo x=%x%

pause&exit


:replaceEqualSign in <variable> with <newString>
    setlocal enableDelayedExpansion

        set "_s=!%~2!#"
        set "_r="

        :_replaceEqualSign
            for /F "tokens=1* delims==" %%A in ("%_s%") do (
                if not defined _r ( set "_r=%%A" ) else ( set "_r=%_r%%~4%%A" )
                set "_s=%%B"
            )
        if defined _s goto _replaceEqualSign

    endlocal&set "%~2=%_r:~0,-1%"
exit /B

Как вы уже видели, вы используете такую ​​функцию:

call :replaceEqualSign in variableName with newString
3 голосов
/ 05 марта 2012

setlocal enableDelayedExpansion следует переместить после вашего старого назначения = %% B, если %% B содержит !.

Проблема "t" легко решить в цикле с помощью другого FORпеременная

For /F "tokens=*" %%B IN (test.txt) DO (
   SET t=is
   SET old=%%B
   SETLOCAL ENABLEDELAYEDEXPANSION
   for /f %%T in ("!t!") do SET new=!old:%%T=!
   ECHO !new!
   ENDLOCAL
)

Нет простого собственного решения для замены =.Вы можете перебирать строку, символ за символом, но это медленно.Лучше всего, вероятно, переключиться на VBScript или JScript или использовать не нативную утилиту.

Если вы действительно хотите сделать это с помощью пакетных команд только для Windows, есть пара интересных идей на http://www.dostips.com/forum/viewtopic.php?t=1485

1 голос
/ 20 июня 2017

ОБНОВЛЕНИЕ : последняя версия скриптов находится здесь: https://sf.net/p/contools (скрипты здесь: https://sf.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools/std/)

Вы можете использовать некоторую последовательность для временной замены специальных символов на заполнителикак? 00,? 01,? 02 и? 03. Я в основном использую этот набор сценариев:

replace_sys_chars.bat:

@echo off

rem Description:
rem   Script to replace ?, !, %, and = characters in variables by respective
rem   ?00, ?01, ?02 and ?03 placeholders.

setlocal DISABLEDELAYEDEXPANSION

set "__VAR__=%~1"

if "%__VAR__%" == "" exit /b 1

rem ignore empty variables
call set "STR=%%%__VAR__%%%"
if "%STR%" == "" exit /b 0

set ?01=!

call set "STR=%%%__VAR__%:?=?00%%"
set "STR=%STR:!=?01%"

setlocal ENABLEDELAYEDEXPANSION

set STR=!STR:%%=?02!
set "STR_TMP="
set INDEX=1

:EQUAL_CHAR_REPLACE_LOOP
set "STR_TMP2="
for /F "tokens=%INDEX% delims== eol=" %%i in ("/!STR!/") do set STR_TMP2=%%i
if "!STR_TMP2!" == "" goto EQUAL_CHAR_REPLACE_LOOP_END
set "STR_TMP=!STR_TMP!!STR_TMP2!?03"
set /A INDEX+=1
goto EQUAL_CHAR_REPLACE_LOOP

:EQUAL_CHAR_REPLACE_LOOP_END
if not "!STR_TMP!" == "" set STR=!STR_TMP:~1,-4!

(
  endlocal
  endlocal
  set "%__VAR__%=%STR%"
)

exit /b 0

restore_sys_chars.bat:

@echo off

rem Description:
rem   Script to restore ?, !, %, and = characters in variables from respective
rem   ?00, ?01, ?02 and ?03 placeholders.

setlocal DISABLEDELAYEDEXPANSION

set "__VAR__=%~1"

if "%__VAR__%" == "" exit /b 1

rem ignore empty variables
call set "STR=%%%__VAR__%%%"
if "%STR%" == "" exit /b 0

setlocal ENABLEDELAYEDEXPANSION

set STR=!STR:?02=%%!
set STR=!STR:?03==!

(
  endlocal
  set "STR=%STR%"
)

set "STR=%STR:?01=!%"
set "STR=%STR:?00=?%"

(
  endlocal
  set "%__VAR__%=%STR%"
)

exit /b 0

Пример:

@echo off

setlocal DISABLEDELAYEDEXPANSION

for /F "usebackq tokens=* delims=" %%i in ("test.txt") do (
  set VALUE=%%i
  call :PROCESS
)
exit /b 0

:PROCESS
if "%VALUE%" == "" exit /b 0

set "VALUE_=%VALUE%"
call replace_sys_chars.bat VALUE_

rem do variable arithmetic here as usual
if not "%VALUE_:?00=%" == "%VALUE_%" echo."%VALUE%" having ?
if not "%VALUE_:?01=%" == "%VALUE_%" echo."%VALUE%" having !
if not "%VALUE_:?02=%" == "%VALUE_%" echo."%VALUE%" having %%
if not "%VALUE_:?03=%" == "%VALUE_%" echo."%VALUE%" having =

rem restore it
call restore_sys_chars.bat VALUE_
echo "VALUE=%VALUE_%"

echo.---

test.txt:

111/222
AAA=BBB
CCC=%DDD%
EEE=!FFF!
FFF=?00?01?02?03

Результат:

"VALUE=111/222"
---
"AAA=BBB" having =
"VALUE=AAA=BBB"
---
"CCC=%DDD%" having %
"CCC=%DDD%" having =
"VALUE=CCC=%DDD%"
---
"EEE=!FFF!" having !
"EEE=!FFF!" having =
"VALUE=EEE=!FFF!"
---
"FFF=?00?01?02?03" having ?
"FFF=?00?01?02?03" having =
"VALUE=FFF=?00?01?02?03"
---

Особенности :

  • Вы можете продолжать использовать стандартную пакетную арифметику между преобразованиями
  • Вы можете использовать символьные заполнители (? 00,? 01,? 02,? 03) в качестве простых значений переменных
1 голос
/ 23 марта 2012

Почему бы не использовать Эдлин?Я не мог найти способ сделать это с одним исходным файлом и без ошибок от Edlin, но просто проигнорировал их с NUL :.Как ни странно, TYPE% 0 включает весь файл, даже если между символами = и! Есть символ конца файла, использование TYPE в командном файле после его запуска не будет работать так же.

@ECHO OFF
GOTO skip
1,1r=!
e
:skip

SET "new==old============="

ECHO %new% > %TEMP%\var.tmp
TYPE %0 > %TEMP%\edlin.tmp

EDLIN %TEMP%\var.tmp < %TEMP%\edlin.tmp > NUL:

SET /P newnew=<%TEMP%\VAR.TMP
ECHO %newnew%

ERASE %TEMP%\VAR.TMP
ERASE %TEMP%\VAR.BAK
ERASE %TEMP%\edlin.tmp
0 голосов
/ 31 января 2019

Я изучал это, потому что мне нужно было избавиться от = в строке типа "test = собирается" Я обнаружил, что при вызове следующего пакетного файла с test = собирается в качестве параметров, у меня есть параметры 1, "тест" и 2, "собирается", в этом пакетном файле.

Итак: пакетный файл 1:

@echo off
call test2.bat test=goingon

batchfile2:

echo arg1: %1
echo arg2: %2

результат:

arg1: test
arg2: goingon
0 голосов
/ 12 апреля 2012

Мой ответ из другого поста, но и здесь он применим:

Есть альтернатива, которая проще. Вместо того, чтобы передавать значение, содержащее знак равенства, попробуйте что-то вроде двоеточия. Затем, благодаря возможности изменить это значение (двоеточие), вы можете преобразовать его обратно в равно. Вот пример:

@echo off
set VALUE1=%1
set VALUE2=%VALUE1::==%
echo value1 = %VALUE1%
echo value2 = %VALUE2%

Когда вы запускаете пакетный файл, вызывайте его так:

C:\>myBatch name:someValue

Вывод будет:

value1 = name:someValue
value2 = name=someValue

Если в имени или значении есть пробел, вам придется решать другие проблемы. Вам нужно будет обернуть всю строку в двойные кавычки. Но тогда у вас есть проблема необходимости избавиться от них. Это также может быть обработано, как это:

@echo off
cls
set PARAM=%1
set BASE=%PARAM:"=%
set PAIR=%BASE::==%

rem Either of these two lines will do the same thing - just notice the 'delims'
rem for /f "tokens=1,2 delims=:" %%a in ("%BASE%") do set NAME=%%a & set VALUE=%%b
rem for /f "tokens=1,2 delims==" %%a in ("%PAIR%") do set NAME=%%a & set VALUE=%%b

for /f "tokens=1,2 delims=:" %%a in ("%BASE%") do set NAME=%%a & set VALUE=%%b

echo param = %PARAM%
echo base  = %BASE%
echo pair  = %PAIR%
echo name  = %NAME%
echo value = %VALUE%

При запуске этого командного файла вот так:

C:\>myBatch "some name:another value"

Вывод будет:

param = "some name:another value"
base  = some name:another value
pair  = some name=another value
name  = some name
value = another value

Надеюсь, что это поможет другим в их стремлении выиграть бой с пакетными файлами.

Майк В.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...