조건부로 '시간'을 통해 서브 쉘을 전달하려면 어떻게해야합니까?


9

와 단일 단계를 측정하는 데 사용되는 Vagrant 상자에 대한 설정 스크립트가 time있습니다. 이제 시간 측정을 조건부로 활성화 또는 비활성화하고 싶습니다.

예를 들어, 이전에 한 줄은 다음과 같습니다.

time (apt-get update > /tmp/last.log 2>&1)

이제 나는 단순히 다음과 같이 할 수 있다고 생각했습니다.

MEASURE_TIME=true
[[ $MEASURE_TIME = true ]] && TIME="time --format=%e" || TIME=""

$TIME (apt-get update > /tmp/last.log 2>&1)

그러나 이것은 작동하지 않습니다.

syntax error near unexpected token `apt-get'
`$TIME (apt-get update > /tmp/last.log 2>&1)'

여기서 무슨 문제가 있습니까?


3
플럭스 커패시터 가 작동 하려면 목표 속도에 도달하면 됩니다.)
goldilocks

2
@goldilocks 당신은 자석을 의미 합니까? ;)
CVn

답변:


13

서브 쉘의 시간 을 정하려면 명령이 아닌 time keyword 가 필요합니다 .

time문자 입력시 키워드, 언어의 부분은, 그러한로 인식하고 명령의 첫 번째 단어로 (그리고의 경우 ksh93, 그 다음 토큰은 시작하지 않습니다 -). 입력해도 "time"혼자서 작동하지 않습니다 $TIME( time대신 명령을 호출하는 것으로 간주 됨 ).

다른 구문 분석이 수행되기 전에 확장되는 별칭을 여기에서 사용할 수 있습니다 (쉘이 해당 time키워드를 인식하게 함 ).

shopt -s expand_aliases
alias time_or_not=
TIMEFORMAT=%E

MEASURE_TIME=true
[[ $MEASURE_TIME = true ]] && alias time_or_not=time

time_or_not (apt-get update > /tmp/last.log 2>&1)

time 키워드 (제외 옵션을 고려하지 않습니다 -p에서를 bash)하지만, 형식은 설정 될 수 TIMEFORMAT있는 변수 bash. (이 shopt부분은 또한 bash특정 적이며 다른 쉘은 일반적으로 필요하지 않습니다).


"서브 쉘의 시간을 정하려면 time 키워드가 필요합니다"라고 말했습니다. 이 행동이 어느 곳에 기록되어 있는지 궁금합니다.
cuonglm

@cuonglm, seeinfo -f bash --index-search=time
Stéphane Chazelas

3

이 있지만 alias그것을 할 수있는 한 가지 방법은,이 와 함께 할 eval뿐만 아니라 - 그것은 당신이 너무 많은 희망을하지 않는 것을 단지 eval당신이 원하는대로 명령 실행 eval명령 선언 .

나는 aliases를 좋아한다 -나는 항상 그들을 사용하지만, 나는 기능을 더 좋아한다-특히 매개 변수를 처리하는 능력은 aliases에 필요한 명령 위치에서 반드시 확장 할 필요는 없다 .

그래서 당신도 이것을 시도하고 싶을 것이라고 생각했습니다.

_time() if   set -- "${IFS+IFS=\$2;}" "$IFS" "$@" && IFS='
';      then set -- "$1" "$2" "$*"; unset IFS
             eval "$1 $TIME ${3#"$1"?"$2"?}"
        fi

$IFS비트는 주로 관한 것입니다 $*. (가) 있다는 것이 중요 ( subshell bit )하다 또한 쉘 확장의 결과 때문에 구문 분석 문자열 I 사용에 인수를 확장하기 위해 "$*" (하지 eval "$@", 그런데, 당신은 인수의있는 거 특정 모든 공간에 가입 할 수없는) . args 사이의 분리 구분 기호 "$*"는의 첫 번째 바이트 $IFS이므로 값을 지정하지 않고 진행하는 것은 위험 할 수 있습니다. 함수가 저장 그래서 $IFS하는로 설정 \n충분히에 ewline set ... "$*""$3", unset이전에 하나가 있다면 그 값을 재설정, 그것을이야.

다음은 약간의 데모입니다.

TIME='set -x; time'
_time \( 'echo "$(echo any number of subshells)"' \
         'command -V time'                        \
         'hash time'                              \
      \) 'set +x'

당신은 내가 $TIME거기에 값을 두 가지 명령을 넣은 것을 보았습니다 – 어떤 숫자도 괜찮습니다 – 아무 것도 없더라도 – 그것이 이스케이프되고 올바르게 인용되어 있는지 확인하십시오 – 그리고 똑같은 주장이 _time()있습니다. 그것들은 실행될 때 모두 단일 명령 문자열로 연결되지만 각 arg는 고유 한 \newline을 얻으므로 상대적으로 쉽게 퍼질 수 있습니다. 또는 원하는 경우 하나를 하나로 \n묶어서 ewlines 또는 semi-colon 또는 what-have-you로 분리 할 수 ​​있습니다. 하나의 인수가 스크립트를 호출 할 때 자신 만의 라인을 작성하는 것이 편한 명령을 나타내는 지 확인하십시오. \(예를 들어 결국에는을 따르는 한 괜찮습니다 \). 기본적으로 정상적인 것.

eval위의 코드 조각을 공급 도착은 다음과 같습니다

+ eval 'IFS=$2;set -x; time (
echo "$(echo any number of subshells)"
command -V time
hash time
)
set +x'

결과는 다음과 같습니다.

산출

+++ echo any number of subshells
++ echo 'any number of subshells'
any number of subshells
++ command -V time
time is a shell keyword
++ hash time
bash: hash: time: not found

real    0m0.003s
user    0m0.000s
sys     0m0.000s
++ set +x

hash오류 내가 가지고 있지 않은 것을 나타냅니다 /usr/bin/time설치 (I하지 않기 때문에)command우리가 실행되는 시간을 알고하자. 후행 set +x이후에 실행되는 또 다른 명령 time 입니다 (가능한 경우)eval . 입력 할 때 입력 명령에주의하는 것이 중요합니다 .


그것을하지 않는 이유는 _time() { eval "$TIME $@"; }무엇입니까? 함수를 사용하면 변수에 다른 범위 (서브 쉘에는 문제가되지 않음)를 도입하는 단점이 있습니다.
Stéphane Chazelas

@ StéphaneChazelas- "$@"확장 의 인용문 때문에 . 나는 하나의 인수를 좋아한다 eval-그렇지 않으면 무섭다. 음 .... 다른 범위에 대해 어떻게 의미합니까? 나는 그것이 단지 function기능 이라고 생각했습니다 .
mikeserv

eval실행하기 전에 인수를 결합합니다. 이는 매우 복잡한 방식으로 수행하려는 것입니다. 그 의미 _time 'local var=1; blah'그 만들 것 var그 로컬 _time또는 그 _time 'echo "$#"'를 인쇄 할 $#이의 _time하지가 호출자의, 기능.
Stéphane Chazelas

@ StéphaneChazelas-나는 당신을 위해 두 개의 탭 완성을 얻었습니다. 맞습니다- eval공간에 인수를 연결합니다. 이것은 내가 의도 한 바는 아니지만 정확하게 내가 여기서하는 일입니다. 나는 그것을 고칠 것입니다. eval보내고 "$*"에 반대하는 "$@"나는 많은 후 집어 습관입니다 실행에로의 command not found인수가 잘못된 장소에 합류했다 때. 어쨌든 args는 궁극적으로 함수에서 실행되지만 호출시 확장 할 수있을 정도로 간단합니다. "$#"어쨌든 내가 할 일 입니다.
mikeserv

멋진 해커의 조각에 +1하지만 ...
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.