매개 변수에서 큰 따옴표 이스케이프


109

유닉스에서는 실행할 수 myscript '"test"'있고 "test".

윈도우에서 cmd내가 얻을 'test'.

큰 따옴표를 매개 변수로 어떻게 전달할 수 있습니까? cmd프로그램을 테스트하기 위해 프로그램을 작성할 필요가 없도록 창 에서 수동으로이 작업을 수행하는 방법을 알고 싶습니다 .


2
Windows 시스템을 만진 지 몇 년이 지났지 만 표준 이스케이프 문자 (백 슬래시 \)가 작동하지 않습니까? 예myscript \"test\"
Gazler 2011 년

아니. 나는 \ test \를 얻습니다. 나는 Windows가 / 대신 \를 사용하기 때문에 백 슬래시를 이스케이프로 사용할 수 없기 때문이라고 생각합니다. 그러나 나는 정말로 모른다.
Bryan Field

어떤 버전의 Windows를 사용하고 있지만 \ "는 Windows 7 (Ultimate)에서 잘 작동합니다.하지만 여러 따옴표를 처리하는 다른 방법이 있습니다 (예 :" ""가 "또는 무언가가 됨).하지만 할 수 없습니다. 알아낼 때 그것이 어떻게 작동하는지.
Codesmith

답변:


22

증상을 빠르게 재현 할 수 없습니다.를 포함 하거나 심지어 포함 myscript '"test"'하는 배치 파일로 시도 하면 모든 따옴표가 표시됩니다.myscript.bat@echo.%1@echo.%~1'"test"'

아마도 다음 ^과 같이 이스케이프 문자를 시도 할 수 있습니다 . myscript '^"test^"'?


3
그렇다면 이 질문에 대한 답변 더 도움이 될까요?
mousio

2
하아! 나는 그것이 wscript잘못 이라고 생각하지 않았을 것입니다 ! Windows
Bryan Field

4
실제로 ^는 나를 위해 작동하지 않았지만 \이 답변에 따라 작동했습니다. stackoverflow.com/questions/2403647/…
kalenjordan

26
Windows : globbing, shell 확장 및 매개 변수 unescaping이 셸 대신 호출되는 실행 파일에 의해 수행되는 OS. 호출 된 실행 파일이 어떤 규칙을 따르는 지 알 수 없습니다.
binki 2014 년

7
귀중한 입력 : blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/... . 캐럿은 실제로에 대해 선택한 이스케이프 문자입니다 cmd.
Peter-Monica 복원

198

따옴표를 이스케이프하는 또 다른 방법은 (아마도 바람직하지는 않지만) 특정 장소에서 사용 된 것으로 나타났습니다 . 여러 개의 큰 따옴표사용하는 것 입니다. 다른 사람의 코드를 읽기 쉽게 만들기 위해 설명하겠습니다.

다음은 기본 규칙 집합입니다.

  1. 이중 인용 부호 그룹에 싸여하지 않을 경우, 공간이 매개 변수를 구분 :
    program param1 param2 param 3에 네 개의 매개 변수를 전달합니다 program.exe:
         param1, param2, param,와 3.
  2. : 이중 인용 그룹은 값 분리기 프로그램에 매개 변수를 전달하는 것과 같은 공간을 무시
    program one two "three and more"로 세 개의 매개 변수를 전달합니다 program.exe:
         one, two,와 three and more.
  3. 이제 몇 가지 혼란을 설명하겠습니다.
  4. 큰 따옴표로 감싸지 않은 텍스트 바로 옆에 나타나는 큰 따옴표 그룹은 하나의 매개 변수로 결합됩니다. 하나의 매개 변수
    hello"to the entire"world역할을합니다 : helloto the entireworld.
  5. 참고 : 이전 규칙은 두 개의 큰 따옴표 그룹이 서로 바로 인접하여 나타날 수 있음을 의미하지 않습니다.
  6. 닫는 따옴표 바로 뒤의 큰 따옴표 는 큰 따옴표 그룹에 인접한 일반 언 래핑 텍스트로 처리되지만 하나의 큰 따옴표 : 만
    "Tim says, ""Hi!"""하나의 매개 변수로 작동합니다.Tim says, "Hi!"

따라서 큰 따옴표에는 세 가지 유형이 있습니다. 여는 따옴표, 닫는 따옴표, 일반 텍스트 역할을하는 따옴표입니다.
마지막으로 헷갈리는 라인의 분석은 다음과 같습니다.

"큰 따옴표 그룹 열기
T 내부 ""
나는 ""s 안에
m 내부 ""
    ""내부-공백이 분리되지 않음
s 내부 ""
내부 ""
y 내부 ""
s 내부 ""
, ""내부
    ""내부-공백이 분리되지 않음
"큰 따옴표로 묶인 그룹 닫기
"인용문이 바로 뒤에옵니다-일반 언 래핑 텍스트로 작동합니다."
""외부의 H-이전 인접 그룹에 결합됩니다.
나는 ""s 밖에-...
! 외부 ""-...
"큰 따옴표 그룹 열기
"큰 따옴표 그룹 닫기
"인용문이 바로 뒤에옵니다-일반 언 래핑 텍스트로 작동합니다."

따라서 텍스트는 4 개의 문자 그룹을 효과적으로 결합합니다 (하나는 아무것도 포함하지 않음) :
Tim says,  첫 번째는 공백을 벗어나기 위해  줄 바꿈 됨 두 번째는 줄 바꿈하지
"Hi!않음 (공백 없음)
세 번째는 큰 따옴표로 묶지 않음
"네 번째, 언 래핑 된 종가입니다.

보시다시피 큰 따옴표 그룹이 없으면 다음 큰 따옴표가 일반 텍스트로 작동하는 대신 큰 따옴표 그룹이 열리기 때문에 아무것도 래핑하지 않아도됩니다.

따라서 따옴표 안팎에서 세 개의 큰 따옴표가 일반 텍스트 이스케이프 처리되지 않은 큰 따옴표 역할을한다는 것을 인식 할 수 있어야합니다.

"팀이 그에게 말했다." ""최근 무슨 일이 일어나고 있습니까? "" ""

Tim said to him, "What's been happening lately?"예상대로 인쇄 됩니다. 따라서 세 개의 따옴표를 항상 안전하게 탈출구로 사용할 수 있습니다.
그러나 그것을 이해하면 기술적으로 불필요한 빈 큰 따옴표 그룹을 추가하기 때문에 끝에 4 개의 따옴표를 2 개로 줄일 수 있음을 알 수 있습니다.

다음은이를 종료하는 몇 가지 예입니다.

프로그램 ab REM은 (a) 및 (b)를 보냅니다.
프로그램 "" "a" ""REM이 전송 ( "a")
프로그램 "" "a b" ""REM은 ( "a) 및 (b")를 보냅니다.
프로그램 "" ""안녕하세요 "" "마이크가 말했다." REM은 ( "안녕하세요,"마이크가 말했다.)
프로그램 ""a ""b ""c ""d ""REM은 ""그룹이 아무것도 감싸지 않기 때문에 (abcd)를 보냅니다.
프로그램 "hello to" ""quotes ""REM이 전송 (hello to "quotes")
프로그램 "" ""hello world ""REM이 전송합니다 ( "hello world").
프로그램 "" "hello"world ""REM이 전송합니다 ( "hello world").
프로그램 "" "hello"world ""REM은 ( "hello) 및 (world")를 보냅니다.
프로그램 "hello" "world" ""REM이 전송합니다 (hello "world").
프로그램 "hello" ""world ""REM이 전송합니다 (hello "world").

마지막 노트 : 나는 어떤 튜토리얼에서도 이것을 읽지 않았습니다. 실험을 통해 모든 것을 생각해 냈습니다. 따라서 내 설명은 내부적으로 사실이 아닐 수 있습니다. 그럼에도 불구하고 위의 모든 예는 주어진대로 평가되므로 내 이론을 검증 (그러나 증명하지는 않음)합니다.

매개 변수 전달 (* .bat 아님)과 함께 * .exe 호출 만 사용하여 Windows 7, 64 비트에서 이것을 테스트했지만 동일하게 작동한다고 가정합니다.


11
+1하지만이 동작은 응용 프로그램에 따라 다릅니다. Windows에서 각 응용 프로그램은 자체 명령 줄 매개 변수를 구문 분석합니다. 여러분이 설명하는 동작은 Microsoft의 표준 C 라이브러리의 동작이라고 생각하며, 대부분의 다른 Windows C 컴파일러에서도 복제 된 것으로 생각합니다.
Harry Johnston

3
마지막 실행에 여러 오류가 있습니다. program "" "ab" ""-> ( "ab"), program "hello to" ""quotes ""-> (hello to "quotes), program" "" "hello world" "-> ("Hello) (세계), program "" "hello"world ""-> ( "hello) (world), program" ""hello "world" "-> ("hello world), program "" ""world ""- > (hello "world)
Thomson

46
... 제가 말할 수있는 것은 Windows 배치 파일에 문제가 있다는 것입니다. 이것은 그리스도를 위해 따옴표피하는 것입니다 . 일종의 로켓 과학 일 필요는 없습니다.
James Ko

4
@JamesKo 나는 더 이상 동의 할 수 없었다. Windows 명령 줄의 난해한 부조리와 불일치는 나를 화나게하지 않습니다. 누가이 쓰레기를 디자인 했나요? 오, 수년에 걸쳐 낭비 된 시간! Unix는 매우 쉽고 비교해 볼 때 매우 의미가 있습니다.
Carlos A. Ibarra


24

이 시도:

myscript """test"""

매개 변수에서 ""는 단일 "로 이스케이프합니다.


1
정답이 아닙니다. 시도 myscript """test test"""와 그렇지 않은 작품은 (첫 번째 매개 변수는 다음과 같이 넘겨됩니다 않습니다 "test. Acutally 세 가지 따옴표가 필요 myscript """"test test""끝에 세 번째 따옴표는 생략 할 수있다, 그러나.
점화기

여기서 모든 따옴표를 제거하고 선택 쿼리 필터에 사용되는 문자열에 매개 변수 값을 배치해야하는 경우 어떻게해야합니까? 누군가 도울 수 있습니까?
SFDC_Learner 2015

2
이 질문에 대해서는 눈에 띄지 않지만 char **argvC 런처에서 spawn또는 같은 함수를 사용하여 다른 프로세스 로 전달해야 할 때 도움이되었습니다 exec. 감사합니다. :-)
virgo47

2

Codesmith의 답변에 대한 Peter Mortensen의 의견에서 인용 한 두 번째 문서는 저에게 상황을 훨씬 더 명확하게했습니다. 이 문서는 windowsinspired.com에서 작성했습니다. 링크는 반복되었습니다. Windows 명령 줄 인수의 인용 및 이스케이프를 이해하는 더 나은 방법 .

더 많은 시행 착오를 거쳐 다음 지침으로 이어집니다.

"캐럿으로 모든 큰 따옴표 를 이스케이프하십시오 ^. 당신은 Windows 명령 쉘에 특별한 의미를 가진 다른 문자를 원하는 경우 (예를 들어, <, >, |, &) 대신에, 다음도 캐럿로 탈출 일반 문자로 해석된다.

프로그램 foo 가 명령 줄 텍스트를 받고 "a\"b c" > d출력을 out.txt 파일로 리디렉션하도록 하려면 Windows 명령 셸에서 다음과 같이 프로그램을 시작합니다.

foo ^"a\^"b c^" ^> d > out.txt

경우 foo는 해석 \"리터럴 큰 따옴표로하고 기대하는이 공백, 다음을 포함를 단락 인수에 큰 따옴표 이스케이프 foo는 하나 개의 인수 지정하는 것과 해석 명령 a"b c, 하나 개의 인수 >, 하나 개의 인수를 d.

대신 foo가 큰 따옴표 ""를 리터럴 큰 따옴표로 해석하면 프로그램을 다음과 같이 시작하십시오.

foo ^"a^"^"b c^" ^> d > out.txt

인용 된 문서의 주요 통찰력은 Windows 명령 셸에서 이스케이프 처리되지 않은 큰 따옴표가 두 가지 가능한 상태 사이의 전환을 트리거한다는 것입니다.

추가 시행 착오는 초기 상태에서 리디렉션 (파일 또는 파이프로)이 인식되고 캐럿 ^이 큰 따옴표를 이스케이프하고 캐럿이 입력에서 제거 된다는 것을 의미합니다 . 다른 상태에서는 리디렉션이 인식되지 않으며 캐럿이 큰 따옴표를 이스케이프하지 않으며 제거되지 않습니다. 이러한 상태를 각각 '외부'및 '내부'라고합시다.

명령의 출력을 리디렉션하려면 리디렉션에 도달했을 때 명령 셸이 외부 상태에 있어야하므로 리디렉션 앞에 이스케이프 처리되지 않은 (캐럿으로) 큰 따옴표가 짝수 여야합니다. foo "a\"b " > out.txt작동하지 않습니다-명령 셸 은 출력을 out.txt로 리디렉션하는 대신 결합 된 명령 줄 인수로 전체 "a\"b " > out.txtfoo 에 전달합니다 ."a\"b "

foo "a\^"b " > out.txt캐럿 ^이 이스케이프 문자가 아닌 일반 문자 인 내부 상태에서 발생 하기 때문에 작동 하지 않으므로 foo에"a\^"b " > out.txt 전달됩니다 .

(희망대로) 항상 작동하는 유일한 방법은 리디렉션이 작동하기 때문에 명령 셸을 항상 외부 상태로 유지하는 것입니다.

리디렉션 (또는 명령 셸에 특별한 의미가있는 다른 문자)이 필요하지 않으면 캐럿 없이도 할 수 있습니다. 경우 foo는 해석 \"리터럴 큰 따옴표로는, 당신은 그것을 호출 할 수 있습니다

foo "a\"b c"

그런 다음 foo"a\"b c"결합 된 인수 텍스트로 수신 하고이를.와 같은 단일 인수로 해석 할 수 있습니다 a"b c.

이제-마지막으로-원래 질문으로. myscript '"test"'Windows 명령 셸에서 호출 '"test"'하면 myscript로 전달 됩니다 . 분명히 myscript 는 작은 따옴표와 큰 따옴표를 인수 구분 기호로 해석하고 제거합니다. 당신은 무엇을 알아낼 필요 로 myscripf는 문자 그대로 따옴표로 받아 다음 사용하여 명령에 그 지정 ^Windows 명령 쉘에 특별한 의미를 가지고있는 문자를 이스케이프 할 수 있습니다. myscript유닉스에서도 사용할 수 있다는 점을 감안할 때 아마도 \"트릭을 수행 할 것입니다. 시험

myscript \^"test\^"

또는 리디렉션이 필요하지 않은 경우

myscript \"test\"

감사합니다! 나는 cmd 프롬프트 텍스트가 cmd 프롬프트 텍스트로 에코되는 vbscript를 실행하려고 벽에 내 머리를 치고 있었는데-나는 이것을 상속 받았으며 따옴표를 피하는 방법을 알아낼 수 없었습니다.
PopeDarren

0

cmd에서 powershell을 호출하고 따옴표를 전달하고 여기에서 이스케이프하지 않습니다. 억양 악센트는이 Win 10 Surface Pro에서 큰 따옴표를 피하는 데 사용되었습니다.

>powershell.exe "echo la`"" >> test
>type test
la"

다음은 다른 문자가 큰 따옴표를 이스케이프하기 위해 얻은 출력입니다.

la\
la^
la
la~

다른 따옴표를 사용하여 따옴표를 이스케이프하면 따옴표가 없습니다. 보시다시피 문자 자체가 입력되었지만 큰 따옴표를 이스케이프하지 않았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.