2014-10-01 3 views
0

좋아요, 명령에서 일부 입력을 듣는 스크립트가 있습니다. 지금까지 도착한 모든 것을 조작 할 수 있기를 원하지만 궁금해하기 시작합니다. read으로도 가능하다면 대신, 당신이 볼 수 있듯이 16 자 사용할 수있을 때의 read_output 기능은 텍스트를 인쇄 할사용 가능한 문자 만 읽음

#!/bin/bash 
long_running_task() { 
    i=0 
    while [ $i -lt 10 ]; do 
     i=$(($i + 1)) 
     printf '%s' "Task $i " 
     sleep 1 
    done 
} 

read_output() { 
    status=0 
    while [ $status = 0 ]; do 
     IFS='' read -rd '' -n 16 text; status=$? 
     [ -z "$text" ] && continue 

     printf '%s %s' "(${#text})" "$text" 
    done 
    echo 
} 

long_running_task | read_output 

(또는 입력의 끝에 도달) : 여기

무슨 뜻인지의 예 사용할 수있는 것을 인쇄합니다.

불행히도 장시간 실행되는 작업의 출력을 제어 할 수 없기 때문에 단순히 다른 구분 기호를 선택할 수는 없습니다. 현재 내가 알고있는이 문제를 해결할 수있는 유일한 방법은 read 한 번에 하나의 문자 만 가져 오는 것입니다.하지만 이것은 대단히 비효율적입니다.

read 또는 그 밖의 다른 방법으로 입력을 가져올 수있는 방법이 있습니까?하지만 입력이 끝났는지 여부를 감지 할 수있는 방법을 제공합니다 (단순히 아니오 출력은 아직 캡처 할 수 있습니까?)

내가 현재 작업하고있는 환경은 bash입니다. 따라서 모든 bash 관련 솔루션을 허용 하겠지만 휴대용 옵션이있는 경우 해당 옵션도 볼 수 있습니다. 합리적인 시간 내에 명령이 반환되는 경우 명령이 얼마나 빨리 리턴되는지는 중요하지 않습니다 (그래서 몇 초마다 출력을 조회 할 수 있습니다).

[편집] 문제에 대한 혼란 거기 때문에, 나는 더 많은 기능 예를 제공하려고합니다 : 아직도

#!/bin/bash 
long_running_task() { 
    i=0 
    while [ $i -lt 10 ]; do 
     i=$(($i + 1)) 
     printf '%s' "Waiting $i second(s)… " 
     sleep $i 
     printf '%s\n' 'done.' 
    done 
} 

NL=$'\n' 
log() { 
    status=0 
    while [ $status = 0 ]; do 
     IFS='' read -rd '' -n 16 text; status=$? 
     [ -z "$text" ] && continue 

     printf '%s' "${text/$NL/$NL[$(date +%R)] }" 
    done 
} 

long_running_task | log 

조금 단순한,하지만 당신이 볼 수있는이 긴 출력을합니다 실행중인 작업과 프로세스 new-lines은 필요로하는 줄의 시작 부분에 타임 스탬프를 추가합니다. 그것은 완벽하지는 않지만 잘하면 기본 아이디어를 제공합니다. 이것은 실제로하고 싶은 것이 아니지만 새로운 라인을 처리해야하며 불행히도 이것이 유일한 방법 인 것 같습니다. read으로 기다리면 반응이 충분하지 않습니다.

+0

내가하려는 일을 이해했다면 관심있는 크기로'16'을 줄여야합니다. 인쇄하고자하는 것보다 작 으면'read_output '읽는 문자가 어떤 값을 만족시키고 그 다음에 합계를 인쇄 할 때까지. 별도의 파일 설명자 (예 : 임시 파일)에 각 문자를 기록하고 증분 값에 관심이있는 경우 임시 파일을 들여다 볼 수 있습니다. 네가 좋아하는 것을 찾을 때까지 '16 '의 길이로 놀아 라. 원하는 경우 모든 문자를 '1'로 읽을 수 있습니다. –

+0

당신이 달성하려고하는 것을 쉽게 알 수 있도록 예상 출력을 줄 수 있습니까 – Ram

+0

bash에서 비동기 읽기가 필요합니다. 읽기에는 시간 초과 옵션이 있습니다. 짧은 시간에 원하는대로 사용할 수 있습니다. – user3132194

답변

1

@Haravikk는 : 귀하의 질문에 내 밀접하게 here on SO

불행하게도 많은 실험 관한 내가 @chepner에서 가져온 유일한 대답은 read이가 원하는 것을 할 수 있도록하는 쉬운 방법이 없다고 생각하는 저를 이끌어 해야 할 것. 그것은 후에 문자의 미리 정의 된 번호 다음에

  • 을 줄 바꿈 (또는 적어도 zsh을 다른 사용자 정의 분리)
  • 를 얻을 후

    • : read은 세 가지 방법으로 텍스트의 덩어리를 삼킬 수 있다는 것 미리 정의 된 시간 제한

    추신 : 상상 당신의 read_output 기능은 문자열 대체를 수행하는 것이, 예를 들면 : 그것은 도착 어떤 read을하지 않을 것이라고 의미 지금까지한다 sed "s/Hello/World/g"이고 작업 시간이 Hel이고 오랜 시간이 지난 후에 lo이 발생합니다.청크로 출력을 읽는 것은 대체를 놓친다. 아마 read_output의 목적과 반대가 될 것이다. 대체를 잡는 것은 (시간 기반 또는 문자 수 기반 알고리즘에 기반하여) 청크를 가져오고 이전 청크를 연결하고 파싱하는 것을 의미합니다.이 경우 청크는 평범하지 않고 적절한 파서가 필요할 것입니다 read ...

  • 0

    불행히도 나는 타협을 위해 정착해야했습니다. 단일 문자를 읽지 않으려 고하지만 갑자기 도착한 데이터를 차단하는 것이 유일한 옵션 인 것 같습니다.

    그래서 내 솔루션은 다음과 같습니다

    log() { 
        status=0; new_line=1 
        while [ $status = 0 ]; do 
         IFS='' read -rn 1 char; status=$? 
         if [ -z "$char" ]; then 
          [ $status = 0 ] && { printf '\n'; new_line=1; } 
          continue 
         fi 
    
         [ $new_line = 1 ] && { printf '%s' "[$(date +%R)] "; new_line=0; } 
         printf '%s' "$char" 
        done 
    } 
    

    이 대부분의 쉘 환경에서 작동합니다 실제로 순수한 쉘 버전이며, (단지 bash는, 내가 뭔가를 놓친 제외). 물론 stdout으로 출력하는 것은 괜찮지 만 출력이 파일에 적용되도록하려면 tee 또는 printf 문을 파일 설명자로 전달해야합니다. 그렇지 않으면 매우 느립니다 (이후 모든 문자에 대해 파일을 다시 열어줍니다).

    물론 pythonperl과 같은 다른 언어가 전체적으로 더 좋은 솔루션 일 수 있습니다. 사용 가능한 경우이를 사용 하겠지만 내 후퇴가되어야합니다. 나는 또한 그것의 사용을 선택적으로 만들 것이라고 생각한다. 그래서 그것들은 그들이 실행하는 프로그램의 부분적인 입력을 기대하는 스크립트에만 사용된다.

    관련 문제