eplawless의 자체 답변은 간단하고 효과적으로 자신의 특정 문제를 해결 "
합니다. 전체 인수 목록의 모든 인스턴스를으로 대체합니다. 이는 \"
Bash가 큰 따옴표로 묶인 문자열 내부에 큰 따옴표를 표시해야하는 방식입니다.
일반적으로 Windows 명령 줄 인터프리터를 사용하여 큰 따옴표로 묶인 문자열 내에서 큰 따옴표를 이스케이프하는 방법에cmd.exe
대한 질문에 대답하려면 Windows 명령 줄 인터프리터 (명령 줄에서 종종 "DOS 프롬프트"라고 잘못 불림-또는 배치 파일에서) : PowerShell 을 보려면 하단을 참조하십시오 .
tl; dr :
당신은 해야한다 사용""
하는 캐릭터 라인을 통과 할 때 A (같아)에 배치 파일 당신은 할 수 있습니다 사용 ""
하여 만든 응용 프로그램과 함께 마이크로 소프트 의 C / C ++ /. NET 컴파일러 한다 ( 도 동의\"
), 윈도우에있는이 파이썬과 Node.js를 포함합니다 :
\"
되는 요구 - 유일한 옵션으로 - 많은 다른 프로그램 (! 예를 들면, 루비, 펄, 심지어 마이크로 소프트의 Windows PowerShell을 ())하지만, 그 사용은 안전하지 않습니다 :
\"
Windows PowerShell을 포함 하여 외부에서 문자열 을 전달할 때 많은 실행 파일 및 인터프리터가 필요 로하는 것입니다. 또는 Microsoft 컴파일러 ""
의 경우 대안으로 지원을 지원 하지만 궁극적으로 인수 목록을 구문 분석하는 것은 대상 프로그램에 달려 있습니다. .
- 예:
foo.exe "We had 3\" of rain."
- 그러나를 사용하면
\"
명령 및 / 또는 입력 / 출력 리디렉션이 원치 않는 임의의 실행으로 이어질 수 있습니다 .
- 다음 문자는 이러한 위험을 나타냅니다.
& | < >
- 예를 들어, 다음은 의도하지 않은
ver
명령 실행을 초래합니다 . 해결 방법에 대한 설명과 다음 글 머리 기호는 아래를 참조하십시오.
foo.exe "3\" of snow" "& ver."
- 의 경우 Windows PowerShell을 ,
\""
그리고 "^""
강력한, 그러나 제한 대안 (아래 "... PowerShell에서의 CLI 호출"절을 참조하십시오).
당신이 사용해야하는 경우 \"
, 단지 3가 안전한 방법 그러나이다, 아주 성가신 : 팁에 모자 TS 자신의 도움이.
사용 (아마도 선택적 ) 변수 확장을 지연 배치 파일에서, 당신은 수있는 문자 저장 \"
A의 변수 , 안쪽 변수 것을 참조 "..."
하여 문자열 !var!
구문 참조 - TS의 도움이 대답 .
- 위의 접근 방식은 번거롭지 만 체계적으로 적용 할 수 있고 어떤 입력으로도 견고하게 작동한다는 장점이 있습니다 .
LITERAL 문자열 (VARIABLES를 포함하지 않는 문자열)을 사용하는 경우에만 유사하게 체계적인 접근 방식을 얻 ^
습니까? 범주 적으로- 모든 cmd.exe
메타 문자를 이스케이프 : " & | < >
및-변수 확장을 억제하려는 경우- %
:
foo.exe ^"3\^" of snow^" ^"^& ver.^"
그렇지 않으면 닫는 구분 기호 로 잘못 해석 되어 따옴표가없는 것으로 간주 되는 문자열 부분을 인식하여 문자열을 공식화cmd.exe
\"
해야합니다 .
있는 그대로 쉘 메타 함유 부 : ^
그들을 -escape; 위의 예를 사용하면- 이스케이프 &
해야합니다 ^
.
foo.exe "3\" of snow" "^& ver."
부분에 와 %...%
스타일 변수 참조 : 그 보장 cmd.exe
(A)의 그 부분을 고려 "..."
문자열을 하고 - 변수 값 자체는 포함하지, 불균형 인용 할 수 있다는 것을 도 항상 가능한 것은 아니다 .
배경 정보는 계속 읽으십시오.
배경
참고 : 이것은 내 실험을 기반으로합니다. 내가 틀렸다면 알려주세요.
Unix 계열 시스템의 Bash와 같은 POSIX 계열 쉘 은 인수 목록 (문자열)을 토큰 화 한 다음 대상 프로그램에 개별적 으로 인수를 전달 합니다. 다른 확장 중에서 인수 목록을 개별 단어로 분할 (단어 분할)하고 결과 단어 (인용문 제거). 대상 프로그램은 넘겨진다 배열 의 개별 인수 와 함께, 구문 인용 부호를 제거 .
반대로 Windows 명령 인터프리터는 인수 목록을 토큰 화하지 않고 인용 문자를 포함하여 모든 인수로 구성된 단일 문자열을 전달합니다 . -대상 프로그램에.
그러나 일부 전처리는 단일 문자열이 대상 프로그램에 전달되기 전에 발생합니다 : ^
이스케이프 문자. 큰 따옴표로 묶인 문자열 외부는 제거되고 (다음 문자를 이스케이프합니다.) 변수 참조 (예 :)%USERNAME%
가 보간됩니다. 첫째.
따라서 Unix와 달리 인수 문자열을 구문 분석하고 따옴표를 제거하여 개별 인수로 나누는 것은 대상 프로그램의 책임입니다. 따라서, 다른 프로그램이 가설 탈출 방법을 다른 요구할 수 있습니다 및 입니다 단일 탈출 메커니즘이 없습니다 보장 모든 프로그램 작업에이 - https://stackoverflow.com/a/4094897/45375은 윈도우 명령 줄은 무정부 상태에 우수한 배경을 포함 파싱.
실제로 \"
는 매우 일반적이지만 안전하지는 않습니다. 위에서 언급했듯이 .
cmd.exe
자체적 \"
으로 이스케이프 된 큰 따옴표 로 인식되지 않기 때문에 명령 줄에서 나중에 토큰을 인용되지 않은 것으로 잘못 해석하고 잠재적으로 명령 및 / 또는 입력 / 출력 리디렉션 으로 해석 할 수 있습니다 .
한마디로 : 다음 문자가 따른다면 문제는, 표면 열거 나 불균형을 \"
:& | < >
; 예를 들면 :
foo.exe "3\" of snow" "& ver."
cmd.exe
\"
일반 큰 따옴표로 잘못 해석 한 결과 다음 토큰이 표시 됩니다.
"3\"
of
snow" "
- 쉬다:
& ver.
따옴표 가 붙지 않는다고cmd.exe
생각 하기 때문에 (명령 시퀀스 연산자), 실행할 명령의 이름이 뒤 따르는 것으로 해석합니다 ( - 무시 됨, 의 버전 정보 보고 ).
전반적인 효과는 다음과 같습니다.& ver.
&
ver.
.
ver
cmd.exe
- 첫째,
foo.exe
처음 3 개의 토큰으로 만 호출 됩니다.
- 그런 다음 명령
ver
이 실행됩니다.
우발적 인 명령이 해를 끼치 지 않는 경우에도 모든 인수가 전달되는 것은 아니기 때문에 전체 명령이 설계된대로 작동하지 않습니다.
많은 컴파일러 / 통역 만 인식\"
등이,에서 호출 GNU C / C ++ 컴파일러, 파이썬, 펄, 루비, 심지어 마이크로 소프트의 Windows PowerShell을 - cmd.exe
- Windows PowerShell을위한 (제한 사항)을 제외하고와 \""
, 그들을위한 간단한 해결책은 없다 이 문제에.
기본적으로 명령 줄의 어느 부분이 인용되지 않은 것으로 잘못 해석되는지 미리 알고 있어야 하며 해당 부분 ^
의 모든 인스턴스를 선택적으로 이스케이프해야합니다 & | < >
.
대조적으로의 사용 ""
은 SAFE 이지만 유감스럽게도 Microsoft 컴파일러 기반 실행 파일 및 배치 파일 ( 배치 파일 의 경우 위에서 설명한 단점이 있음) 에서만 지원되며 , 주목할만한 PowerShell 은 제외됩니다 . 다음 섹션을 참조하십시오.
cmd.exe
또는 POSIX 유사 쉘 에서 PowerShell의 CLI 호출 :
참고 : PowerShell 내에서 인용이 처리되는 방법은 하단 섹션을 참조하세요 .
외부에서 호출 되는 경우 ( 예 : cmd.exe
from, 명령 줄 또는 배치 파일에서) :
PowerShell을 [코어] + V6 정상적으로 인식""
(외에\"
양이다) 사용이 안전하고 공백 보존 .
pwsh -c " ""a & c"".length "
부러지지 않고 올바르게 산출 6
Windows PowerShell을 (그의 마지막 버전 5.1입니다 기존 버전) 인식 만 \"
하고, 또한 Windows에서 """
와보다 강력한 \""
/"^""
(비록 내부적으로 PowerShell을 사용하는`
따옴표 문자열에서 이스케이프 문자로도 받아 들인다는""
- 아래 섹션 참조)
/ 배치 파일 에서 Windows PowerShell 호출 :cmd.exe
""
breaks 는 근본적으로 지원되지 않기 때문입니다.
powershell -c " ""ab c"".length "
-> 오류 "문자열에 종결자가 없습니다."
\"
및 """
작업 원칙적으로 ,하지만하지 않습니다 안전 :
powershell -c " \"ab c\".length "
의도 한대로 작동합니다. 출력합니다 5
( 2 공백에 )
- 그러나
cmd.exe
메타 문자는 이스케이프되지 않는 한 명령을 중단 하기 때문에 안전하지 않습니다 .
powershell -c " \"a& c\".length "
breaks , 때문에 &
이스케이프해야합니다.^&
\""
이다 안전 하지만, 정상화 내부 공백 바람직하지 않은 될 수있다 :
powershell -c " \""a& c\"".length "
4
2 개의 공백이 1로 정규화 되었기 때문에 (!)를 출력 합니다.
"^""
특히 안전하고 공백을 보존하는 Windows PowerShell을 위한 최선의 선택 이지만 PowerShell Core (Windows의 경우)는\""
공백 정규화 와 동일 합니다. 이 접근 방식을 발견 한 Venryx에 대한 공로 를 인정 합니다.
powershell -c " "^""a& c"^"".length "
작동 : 중단되지 않음-에도 불구하고 &
- 및 출력 5
, 즉 올바르게 보존 된 공백.
PowerShell을 코어 : pwsh -c " "^""a& c"^"".length "
작동 하지만, 출력 4
, 즉 정규화 공백 , 같은 \""
않습니다.
온 유닉스 플랫폼 (리눅스, 맥 OS) 호출시 PowerShell을 [코어] 의 CLI를 pwsh
, (A)로부터 셸 같은 형상 POSIXbash
:
당신은 있어야 사용\"
하지만, 이는 안전하고 공백 보존 모두 :
$ pwsh -c " \"a& c|\".length" # OK: 5
관련 정보
^
인용되지 않은 문자열 의 이스케이프 문자로만 사용할 수 있습니다. 큰 따옴표로 묶인 문자열 내부 ^
는 특별하지 않으며 리터럴로 취급됩니다.
- 주의 사항 : 명령문에 전달 된 in 매개 변수의 사용 이 중단되었습니다
^
call
(이는 call
다른 배치 파일 또는 바이너리를 호출하고 동일한 배치 파일에서 서브 루틴을 호출하는 두 가지 사용 모두에 적용됩니다 ) :
^
큰 따옴표 값의 인스턴스 는 설명 할 수없이 두 배가됩니다. 되어 전달되는 값을 변경합니다. 예 : 변수 %v%
에 리터럴 값이 포함 된 경우a^b
, call :foo "%v%"
양수인 "a^^b"
에게 (!) %1
서브 루틴 (최초의 매개 변수) :foo
.
- 인용 부호 의 사용
^
으로 call
되어 완전히 파괴 한다는 점에서는 ^
더 이상 특수 문자를 이스케이프 사용할 수 없습니다 : 예를 들어,call foo.cmd a^&b
조용히 휴식을 (대신 문자 그대로 전달하는a&b
너무foo.cmd
하지 않고 사건을 것 같은 call
) -foo.cmd
도 호출되지 않습니다, 적어도 Windows에서 (!) 7.
리터럴을 이스케이프하는 %
것은 특수한 경우입니다 . 안타깝게도 문자열이에 지정되었는지 여부에 따라 구별되는 구문 이 필요합니다. 배치 파일 내부 와 명령 줄 합니다 . 참조 https://stackoverflow.com/a/31420292/45375를
- 요약 : 배치 파일 내에서
%%
. 명령 줄에서는 %
이스케이프 할 수 없지만 ^
시작, 끝 또는 따옴표 없는 변수 이름 내부에 a를 넣으면 문자열 (예echo %^foo%
변수 확장 (보간)을 방지 할 수 있습니다. %
변수 참조의 일부가 아닌 명령 줄의 인스턴스는 리터럴 (예 :)로 처리됩니다 100%
.
일반적으로 공백과 특수 문자를 포함 할 수있는 변수 값으로 안전하게 작업하려면 다음을 수행하십시오 .
- 할당 : 묶어야 두 변수의 이름과의 값을 하나의 큰 따옴표 쌍 ; 예를 들어,
set "v=a & b"
리터럴 값 a & b
을 변수에 할당 합니다 %v%
(대비 적으로set v="a & b"
큰 따옴표를 값의 일부로 만듭니다). 리터럴 %
인스턴스를 다음과 같이 이스케이프 합니다 %%
(배치 파일에서만 작동-위 참조).
- 참조 : 값이 보간되지 않도록 큰 따옴표 변수 참조 ; 예 :
echo "%v%"
의 값 %v%
을 보간 및 인쇄 하지 않습니다 "a & b"
(그러나 큰 따옴표도 항상 인쇄 됨). 대조적으로, echo %v%
그대로 통과 a
에 echo
, 해석을&
하고 명령 시퀀스 연산자로 하므로라는 명령을 실행하려고합니다 b
.
또한 위의 경고문 ^
과 함께 재사용 할 수 있습니다 call
.
- 외부 언급 한 바와 같이 프로그램은 일반적으로 당신이 직접해야 할 배치 파일에 매개 변수 주위에 따옴표를 둘러싸는 제거 돌봐 있지만 (예를 들어,
%~1
첫 번째 매개 변수에서 따옴표를 둘러싸는 제거합니다) 슬프게도, 및 직접이 없다 내가 아는 방식으로 큰 따옴표를 묶지 않고echo
충실하게 변수 값을 인쇄 할 수 있습니다 .
- Neil 은 값에 큰 따옴표가 포함되지 않는 한 작동 하는
for
기반 해결 방법을 제공 합니다 . 예 :
set "var=^&')|;,%!"
for /f "delims=" %%v in ("%var%") do echo %%~v
cmd.exe
않습니다 하지 인식 한 -quotes을 를 문자열 구분 기호로 리터럴로 취급되며 일반적으로 공백이 포함 된 문자열을 구분하는 데 사용할 수 없습니다. 또한 작은 따옴표와 그 사이에있는 모든 토큰에 인접한 토큰은 인용되지 않은 것으로 처리되고 cmd.exe
그에 따라 해석됩니다.
- 그러나 대상 프로그램은 궁극적으로 자체 인수 구문 분석을 수행하므로 Ruby와 같은 일부 프로그램은 Windows에서도 작은 따옴표로 묶인 문자열을 인식합니다. 반대로 C / C ++ 실행 파일, Perl 및 Python은이를 인식 하지 못합니다 .
그러나 대상 프로그램에서 지원하더라도 작은 따옴표로 묶인 문자열을 사용하는 것은 바람직하지 않습니다 cmd.exe
..
에서 인용 PowerShell 내 :
Windows PowerShell 은cmd.exe
수년 동안 Windows의 일부였습니다 ( PowerShell Core 는 PowerShell 환경을 macOS 및 Linux에도 가져옴).
PowerShell은 일관되게 작동합니다. 인용과 관련하여 내부적 으로 .
- 큰 따옴표로 묶인 문자열 안에
`"
또는 ""
큰 따옴표를 탈출
- 작은 따옴표로 묶인 문자열 안에
''
를 이스케이프 데
이는 PowerShell 명령 줄에서 작동하며 매개 변수를 PowerShell 스크립트 또는 함수로 전달할 때 PowerShell 내에서 합니다.
(위에서 설명했듯이 외부에서 이스케이프 된 큰 따옴표를 PowerShell로 전달 필요로 \"
하거나, 더 견고\""
다른 작업이 하지 않습니다.)
안타깝게도 PowerShell에서 외부 프로그램을 호출 할 때 PowerShell의 고유 한 인용 규칙을 수용 하고 이를 위해 탈출 해야 할 필요가 있습니다 . 대상 프로그램 :
이 문제가되는 동작은 다음에서 논의되고 요약됩니다. 이 답변
내부 큰 따옴표 더블 -quoted 문자열 :
문자열 고려 "3`" of rain"
PowerShell 내부적으로 리터럴로 변환하는3" of rain
.
이 문자열을 외부 프로그램에 전달 하려면 PowerShell 에 추가 하여 대상 프로그램의 이스케이프를 적용해야합니다 . 삽입 된 큰 따옴표가 다음과 같이 이스케이프 될 것으로 예상하는 C 프로그램에 문자열을 전달하려고한다고 가정하십시오.\"
.
foo.exe "3\`" of rain"
어떻게 참고 가 모두 `"
PowerShell에서의 행복을 위해 - - 및\
- 대상 프로그램의 행복을 만들기 위해 -이 있어야합니다.
동일한 논리가 배치 파일을 호출하는 데 적용되며 여기서 ""
사용해야합니다.
foo.bat "3`"`" of rain"
반대로, 큰 따옴표로 묶인 문자열 에 작은 따옴표를 포함하는 것은 이스케이프 처리가 전혀 필요하지 않습니다.
작은 따옴표로 묶인 문자열 내부의 작은 따옴표 에는 추가 이스케이프가필요하지 않습니다 . PowerShell의 표현 인을고려하십시오.'2'' of snow'
2' of snow
.
foo.exe '2'' of snow'
foo.bat '2'' of snow'
PowerShell은 작은 따옴표로 묶인 문자열을 대상 프로그램에 전달하기 전에 큰 따옴표로 묶은 문자열로 변환합니다.
그러나 작은 따옴표 문자열 내부의 큰 따옴표 는 PowerShell 에 대해 이스케이프 처리 할 필요가 없지만 대상 프로그램에 대해 이스케이프 처리해야합니다 .
foo.exe '3\" of rain'
foo.bat '3"" of rain'
PowerShell을의 V3는 마법의 도입 --%
옵션을 호출, 정지 구문 분석 기호 가 후에 무엇을 전달하여, 고통의 일부를 완화, 해석되지 대한 저장, 대상 프로그램을 cmd.exe
스타일의 환경 변수 참조 (예 %USERNAME%
) 되어 확장; 예 :
foo.exe --% "3\" of rain" -u %USERNAME%
대상 프로그램에 대해서만 임베디드 "
를 이스케이프하는 것이 얼마나 충분한 지 \"
주목하십시오 \`"
.
그러나이 접근 방식 :
- 환경 변수 확장을 피하기 위해 문자 이스케이프를 허용하지 않습니다
%
.
- 배제 직접 PowerShell을 변수와 표현의 사용; 대신 명령 줄은 첫 번째 단계에서 문자열 변수로 빌드 한 다음
Invoke-Expression
두 번째 단계에서으로 호출해야 합니다.
따라서 많은 발전에도 불구하고 PowerShell은 외부 프로그램을 호출 할 때 훨씬 쉽게 탈출하지 못했습니다. 그러나 작은 따옴표 문자열에 대한 지원이 도입되었습니다.
나는 그것이시키는의 유닉스 모델에 적 스위치에 윈도우 세계에서 근본적으로 가능하다면 궁금 쉘은 모든 토큰 및 인용 제거 할 예상 , 프런트까지 , 에 관계없이 대상 프로그램의 다음 대상 프로그램 호출 결과 토큰을 전달하여, 및 .