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.