bash 명령 대체 출력이 이스케이프되는 것을 방지하는 방법은 무엇입니까?


6

bash 스크립트에서 명령 대체를 사용하여 변수를 기반으로 리디렉션 기호를 출력하려고합니다.

IS_VERBOSE=false
curl $BLAH $( $IS_VERBOSE && echo '-i' || echo '> /dev/null' )

즉, 장황한 경우 -i스위치를 추가하고 그렇지 않으면 stdout에서 모든 것을 버립니다. 문제는 IS_VERBOSEfalse 일 때 내 명령이된다는 것입니다.

curl $BLAH \> /dev/null

보다 일반적으로, 명령 대체는 문자 > >> & | # $및 가능하면 다른 문자를 이스케이프합니다 . 명령 대체를 사용하여 이스케이프하지 않고 어떻게 이러한 심볼을 출력 할 수 있습니까?


모든 명령이 대화 형 셸이 아닌 스크립트로 실행되고 있다고 가정합니까? 또한 어떤 쉘을 사용하고 있습니까? 그 배쉬 또는 다른 것입니까?
— terdon

명령이 스크립트에서 실행되고 있습니다. GNU bash, 버전 3.2.57 (1)-릴리스 (x86_64-apple-darwin14)를 사용하고 있습니다. 대화 형 zsh에서 동일한 동작이 나타납니다. 즉 $(echo ">")<tab> 이로 바뀝니다 \>.
— asmodean

리디렉션을 수행하려면 식을 다시 평가해야 할 수도 있습니다. 즉eval curl $BLAH $( $IS_VERBOSE && echo '-i' || echo '> /dev/null' )
— adonis

가 $IS_VERBOSE명령은? 당신은 그것을 하나로 취급하고 있습니다.
— terdon

$ IS_VERBOSE는 변수입니다. 설정 방법을 보여주기 위해 편집하겠습니다.
— asmodean

답변:


5

포지셔닝이 발생한 후 (POSIX의 BTW는 ">"앞의 왼쪽 만 대상으로 할 수 있음) ">"가 있는지 더 이상 평가되지 않으므로 구상 한 접근 방식이 작동하지 않습니다.

POSIX 적합성에 신경 쓰지 않는다면 (이를 'bash'로 태그 한 후에도) 동적으로 오른쪽을 설정하여 해결책을 찾을 수는 있지만 완전히 다른 접근법을 원할 것입니다. https://stackoverflow.com/a/20942015/2261442 사용자 정의 파일 디스크립터를 기반으로 verbose / silent 모드를 자세히 설명하는 다음 게시물을 살펴보십시오 .

해당 게시물에서 발췌 한 코드는 다음과 같이 표시됩니다.

# Some confirmations:
printf "%s\n" "This message is seen at verbosity level 3 and above." >&3
printf "%s\n" "This message is seen at verbosity level 4 and above." >&4
printf "%s\n" "This message is seen at verbosity level 5 and above." >&5

이것은 아름답다! 나는 항상 스크립트가 여러 가지 상세 레벨을 어떻게 처리했는지 궁금했습니다. 나는 이것을 미래의 스크립트로 만들기 시작할 것입니다. 또한 대체 후 리디렉션에 대해 "더 이상 평가가 없습니다"라는 질문에 대한 답변을 얻었으므로 "이스케이프되지 않은"출력을 얻을 수 있다고해도 예상대로 평가되지 않습니다. 감사!
— asmodean

3

나는 이것이 당신의 탈출 문제를 해결하지 못한다는 것을 알고 있지만 (아직 확실하지는 않습니다) man curl 에서 오는 것은 당신이하려는 일을 성취 할 것입니다 :

BLAH=localhost

IS_VERBOSE=true
OPTIONS="-o /dev/null"
$IS_VERBOSE && OPTIONS=""

curl $BLAH -s $OPTIONS
    <html>
    <p>hi</p>
    </html>

IS_VERBOSE=false
OPTIONS="-o /dev/null"
$IS_VERBOSE && OPTIONS="-i"

curl $BLAH -s $OPTIONS

후자는 아무것도 출력하지 않습니다. 그리고 다른 쉘 (bash, sh 등)에 덜 의존적이므로 휴대가 편리합니다.


잘 잡았습니다. 리디렉션은 파일에 출력을 저장하는 더 보편적 인 접근 방식이므로 -o 스위치에 대해 잊어 버렸습니다. 이것이 내가 지금 가고있는 해결책입니다.
— asmodean

2

bash 매뉴얼에 따르면 쉘 확장 순서는 중괄호 확장, 물결표 확장, 매개 변수 및 변수 확장, 명령 대체, 산술 확장, 단어 분할 및 경로 이름 확장 입니다. 또한 명령이 실행되기 전에 (즉, 셸 확장 후) 리디렉션이 발생한다고 명시되어 있습니다. 따라서 다음과 같은 명령이 추론됩니다.

redir='>'
echo value $redir file

과

echo value $(echo '>') file

파일 파일 에 가치 를 넣습니다 .

불행히도 이것은 명령 행이 먼저 구문 분석되고 리디렉션 토큰 이이 단계 에서만 식별 되기 때문에 그렇지 않습니다 . 나중에 명령이 실행되기 전에 해당 토큰을 기반으로 리디렉션이 수행됩니다.

eval curl $BLAH $( $IS_VERBOSE && echo '-i' || echo '> /dev/null' )

명령을 다시 구문 분석하여 작동하므로 리디렉션을 식별하지만 셸 확장을 수행하기도 약간 까다 롭고 예기치 않은 동작이 발생할 수 있습니다.

참고 :>$var 및 bash에는 특별한 처리가 있습니다.>&$var


그것은 이제 많은 의미가 있습니다. 명령을 구문 분석 한 후에 생성 된 리디렉션 토큰은 특별한 의미가 없습니다. 나는 다시 그 실수를 시도하지 않을 것입니다. 이 답변에 감사드립니다! 나는 내가 지금 무슨 일이 일어나고 있는지에 대한 이해 (뿐만 아니라 악에 대한 모호한 사용 사례가 느끼는 evalCOMAND를.
— asmodean
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.