2016-07-15 7 views
2

delayed expansion이 활성화되어있는 동안 substring replacement 구문을 사용하여 특정 하위 문자열을 느낌표로 바꾸려는 경우 파서는 확장을 위해 !을 구별 할 수 없으므로 즉시 (일반) 확장을 사용해야합니다.대체 문자열에는 느낌표를 사용하지만 검색 문자열에는 느낌표를 표시하지 마십시오 (지연 확장을 사용하여 부분 문자열을 대체).

그러나 대체 문자열에서 느낌표를 벗어나는 이유는 무엇입니까? 그리고 검색 문자열의 느낌표가 이스케이프 될 때 왜 필요하지 않고 파괴적일까요?

다음 스크립트 `에 의해, 그 후 역순으로 문자열 !의 대체, 그래서 결과는 (물론 그 자체에 어떤 백 진드기를 포함 할 수 없습니다) 초기 문자열과 동일 할 것으로 예상 :

이 결과는 내가 원하는 것을 확실히하지
@echo off 
setlocal EnableExtensions DisableDelayedExpansion 
rem This is the test string: 
set "STRING=string!with!exclamation!marks!" 
set "DELOFF=%STRING%" 
set "DELOFF=%DELOFF:!=`%" 
set "DELOFF=%DELOFF:`=!%" 
setlocal EnableDelayedExpansion 
set "DELEXP=!STRING!" 
set "DELEXP=%DELEXP:!=`%" 
set "DELEXP=%DELEXP:`=!%" 
echo(original string: !STRING! 
echo(normal expansion: !DELOFF! 
echo(delayed expansion: !DELEXP! 
endlocal 
endlocal 
exit /B 

는 마지막 문자열은 다릅니다

original string: string!with!exclamation!marks! 
normal expansion: string!with!exclamation!marks! 
delayed expansion: stringexclamation 

수 있도록 로하는 ... 라인을 가지고 : ....

set "DELEXP=%DELEXP:`=!%" 

을 따라서 대체 문자열에 느낌표를 탈출, 거기 !^!에 의해 교체, 결과는 내가 예상 정확히 :

original string: string!with!exclamation!marks! 
normal expansion: string!with!exclamation!marks! 
delayed expansion: string!with!exclamation!marks! 

나는 (느낌표 탈출에 모두 교체하고 검색 문자열, 또는 단지 후자에)하지만 다른 탈출 조합을 시도, 결과는 다시 상기 원치 않는 것입니다. 때

나는 게시물 How does the Windows Command Interpreter (CMD.EXE) parse scripts?을 통해 걸어 왔지만 지연된 확장이 발생하고 느낌표가 인식되기 훨씬 전에 정상적인 (즉각적인, 퍼센트) 확장이 이루어 졌다는 것을 알았 기 때문에 그 행동에 대한 설명을 찾을 수 없었습니다. 또한 나중에 캐럿 인식 및 이스케이프가 발생하는 것으로 보입니다. 또한, 문자열 주위에는 큰 따옴표가있어 파서에서 일반적으로 숨기기를 숨 깁니다.

답변

1

사실, 부분 문자열 교체 자체의 경우 이스케이프가 필요하지 않습니다. 나중에 구문 분석 단계에서만 필요합니다. 이유는 다음과 같습니다.

그러나 대체 문자열에서 느낌표를 벗어나는 이유는 무엇입니까?

문제는 이름에서 알 수 있듯이 지연 확장 (!), 마지막 단계 중 하나로서 수행되는 반면, 즉시 (정상은, %) 확장, 아주 초기 단계에서 수행되는 것이다. 따라서 즉시 확장 된 문자열도 지연된 확장 단계를 통과합니다. 증명을 위해 변수 VARValue!X!X에서 0으로 설정 한 다음 echo %VAR%을 실행하면 Value0이 결과로 나타납니다.
그러나 초기 질문으로 돌아 가면 직접 문자열 대체를 사용할 때 대체 문자열은 확장 된 값의 일부이므로 지연된 확장 단계도 통과합니다. 따라서 지연 확장으로 인해 소비되지 않도록 문자 그대로 느낌표를 이스케이프 처리해야합니다.이것은 이스케이프가 대체 자체에 필요하지 않다는 것을 의미합니다. 이스케이프는 실제로 이후에 수행되므로 이스케이프를 포함하여 지정된 대체 문자열이 그대로 적용됩니다.

검색 문자열의 느낌표가 이스케이프 처리되는데 왜 필요하지 않고 파괴적일까요?

즉각적인 확장 후에 캐럿 인식 및 이스케이프가 발생하므로 검색 문자열이 그대로 취급됩니다. 또한 검색 문자열은 바뀌므로 즉치 문자열 대체 문자열의 결과에는 포함되지 않으므로 지연 확장 단계를 거치지 않습니다.


것은 우리가 원래의 예에서 (만 발췌)를 살펴 보자 :

set "STRING=string!with!exclamation!marks!" 
setlocal EnableDelayedExpansion 
set "DELEXP=!STRING!" 
set "DELEXP=%DELEXP:!=`%" 
set "DELEXP=%DELEXP:`=!%" 
echo(delayed expansion: !DELEXP! 
endlocal 

교체 !에 대한 set "DELEXP=%DELEXP:!=`%" 검색합니다. 결과 값은 string`with`exclamation`marks`입니다. 그래서 발생은 물론 발견 될

그대로 ^!를 검색 할 set "DELEXP=%DELEXP:^!=`%" 사용은, (그래서 모든 원본 문자열의 문자 !은 유지했다 그들은 마침내 지연 확장에 의해 처리되었다).

대체품 set "DELEXP=%DELEXP:`=!%"은 을 !으로 바꿉니다. 결과 문자열은 string!with!exclamation!marks!이지만 나중에 지연된 확장에 의해 소모됩니다.

는 결과가 string^!with^!exclamation^!marks^! 그래서 교체 %DELEXP:`=^!%은, 문자 그대로 ^!에 의해 `을 대체 탈출; 지연 확장 단계에서 이스케이프가 처리되어 결국 문자 !과 반환 문자열 string!with!exclamation!marks!가 최종적으로 생성됩니다.


는 포스트 How does the Windows Command Interpreter (CMD.EXE) parse scripts? 따르면 탈출은 지연 확장 단계 인 제 2 위상 발생있다. 첫 번째 이스케이프 (특수 문자 인식 단계 중)가 주변 인용 부호로 인해 비활성화되어 있기 때문에 원래 질문의 예에 적용됩니다 (생략하면 ^^!과 같이 두 번 이스케이프해야합니다).