전체 줄을 기다리지 않고 프로그래밍 출력 앞에 문자열을 추가하려면 어떻게 해야 합니까?

전체 줄을 기다리지 않고 프로그래밍 출력 앞에 문자열을 추가하려면 어떻게 해야 합니까?

SSH를 사용하여 원격 서버에서 명령을 실행하는 스크립트가 있습니다. 출력의 모든 줄 앞에 문자열을 추가하고 싶지만 Remote:전체 줄을 사용할 수 있을 때까지 각 줄이 지연되는 것을 원하지 않습니다. 내 명령의 출력은 다음과 같습니다.

$ myproject-db-push my_database_name
데이터베이스에서 내보내는 중... 완료
데이터 보관 중... 완료
아카이브를 원격으로 업로드하는 중... 완료
원격에서 설치 스크립트 실행
원격: 아카이브를 임시 디렉터리로 압축 해제하는 중... 완료
원격: 데이터베이스 사용: my_database_name
원격: 컬렉션 삭제:
원격: - my_collection_foo
원격: - my_collection_bar
원격: 새 데이터를 가져오는 중... 완료

이 경우 sed다음과 같이 사용하고 있습니다.

echo "$INSTALLCMD" | ssh -T "deploy@$SERVER" | sed -u "s/^/Remote: /"

문제는 내가 설명했듯이부분적인줄이 화면에 인쇄됩니다. 부품 을 제거하면 | sed예상대로 작동합니다. 먼저 다음과 같이 작성됩니다.

새 데이터를 가져오는 중...

그리고 몇 초 후에 라인이 완성됩니다.

새 데이터를 가져오는 중... 완료

나는 sed한 줄씩만 작업할 수 있다고 가정합니다. 버퍼링되지 않은 상태로 설정하려고 시도했지만 여전히 전체 라인을 기다립니다. 이를 수행하는 또 다른 방법이 있습니까?

답변1

sed모든 유틸리티( , awk, grep)가 라인 버퍼링되어 있기 때문에 약간 까다롭습니다 . 즉, 줄이 끝났을 때만(새 줄이 나타났을 때) 출력을 인쇄한다는 의미입니다. 입력된 문자를 문자별로 읽을 수 없습니다.

그래서 테스트를 위해 여러분의 행동을 시뮬레이션하는 작은 시퀀스를 만들었습니다.

{ 
  echo -n "first task: "
  sleep 2
  echo "done"
  echo -n "second task: "
  sleep 2
  echo "done"
}

귀하의 질문과 마찬가지로 first task:2 초 후에 인쇄됩니다 done. 터미널에 복사하여 직접 사용해 보세요.

해결책:

명령 뒤에 다음을 추가합니다.

IFS=
command | { x=1; while IFS= read -d'' -s -N 1 char; do
  [ $x ] && printf "Remote: "
  printf "$char"
  unset x
  [ "$char" == "
" ] && x=1
done; }

설명:

read의 내장은 입력 bash된 문자를 문자별로 읽을 수 있습니다. 이 부분은 read -d'' -s -N 1 char구분 기호를 비활성화 -d''하고 자동 모드를 활성화하며 변수에 -s한 번에 한 문자만 읽습니다 . 그런 다음 명령은 변수가 존재하는지 확인합니다. 그렇다면 새 줄에 있고 "접두사"를 인쇄합니다. 그런 다음 문자를 인쇄합니다. 설정 해제 . 그런 다음 마지막 명령문은 문자가 개행인지 확인합니다. 다음 루프에 개행 문자가 설정 되어 있으면 "접두사"가 인쇄됩니다.-N 1$char$x$x$x1

두 시퀀스를 연결하면 모든 것을 테스트할 수 있습니다.

{ 
  echo -n "first task: "
  sleep 2
  echo "done"
  echo -n "second task: "
  sleep 2
  echo "done"
} | { x=1; while IFS= read -d'' -s -N 1 char; do
  [ $x ] && printf "Remote: "
  printf "$char"
  unset x
  [ "$char" == "
" ] && x=1
done; }

관련 정보