여러 줄의 bash 명령을 변수로 리디렉션하는 방법

여러 줄의 bash 명령을 변수로 리디렉션하는 방법

이 명령을 변수로 리디렉션하고 싶습니다.

{
    printf 'scan on\n\n'
    sleep 10
    printf 'quit \n\n'  
} | bluetoothctl

나는 이것을 시도한다:

variable=$(printf 'scan on\n\n' sleep 10 printf 'quit \n\n' | bluetoothctl)
echo $variable

하지만 빈 출력이 나타납니다. 나는 또한 그것을 분할하려고 시도했습니다.

variable=$(printf 'scan on\n\n' | bluetoothctl)
sleep 10
printf 'quit \n\n'| bluetoothctl
echo $variable

하지만 이번에는

Agent registered
[bluetooth]# quit

stdout변수를 실행할 때 인쇄된 첫 번째 명령의 출력을 어떻게 리디렉션할 수 있나요 ?

답변1

오직:

variable=$(
  {
    printf 'scan on\n\n'
    sleep 10
    printf 'quit \n\n'  
  } | bluetoothctl
)

명령 대체의 내부는 임의의 쉘 코드1일 수 있으며 한 줄에 있을 필요는 없습니다.

bluetoothctl여기서는 전체 파이프의 출력을 캡처하려고 합니다(실제로 다른 모든 명령의 stdout이 파이프로 리디렉션되므로 이는 stdout의 출력이 됩니다 bluetoothctl).

다음을 사용하여 출력을 캡처할 수도 있습니다 bluetoothctl.

{
  printf 'scan on\n\n'
  sleep 10
  printf 'quit \n\n'  
} | variable=$(bluetoothctl)

하지만 에서 bash작동하려면 마지막 파이프라인 구성 요소에 대한 옵션을 설정해야 합니다 lastpipe( shopt -s lastpipe, 비대화형 셸 인스턴스에만 해당).아니요서브셸에서 실행합니다.

그러나 여기서는 파이프가 필요하지 않습니다. 다음과 같이 할 수 있습니다.

variable=$(bluetoothctl --timeout 10 scan on)

변수의 내용을 표시하려면 다음 구문을 기억하세요.

printf '%s\n' "$variable"

아니요 echo $variable.

자세한 내용은 다음을 참조하세요.

여기의 출력에는 bluetoothctl색상 표시 이스케이프 시퀀스와 줄 내용을 지우는 데 사용되는 이스케이프 시퀀스가 ​​포함되어 있습니다. 따옴표 없이 두면 $variable해당 내용이 분할+글로브되어 전달될 임의의 단어 목록이 생성되고 공백으로 구분되어 출력됩니다 echo. echo따라서 마지막 단어가 다음으로 끝나면 모든 내용을 한 줄에 작성하게 됩니다.명확한 선시퀀스(내 테스트에서 수행한 작업 \r\e[K:캐리지 리턴다음은생산라인 끝까지 클리어순서), 빈 줄만 표시됩니다.


1 일부 쉘은 bash일치하지 않는 괄호가 있는 코드를 차단하는 데 사용되지만(예: 코드에 케이스 문 case $x in foo)이나 불균형 주석이 포함된 경우 )) 쉘 파서는 이를 )명령 대체를 닫는 것으로 착각합니다.

답변2

오류는 세미콜론 누락입니다(그렇지 않으면 개행 문자와 동일함). 출력 구조를 보려면 큰따옴표를 추가하세요. 노력하다:

variable=$( { printf 'scan on\n\n' ; sleep 10 ; printf 'quit \n\n' ; } | bluetoothctl)
echo "$variable"

답변3

가능한 대안은 간단한 expect스크립트입니다.

#!/usr/bin/expect

spawn bluetoothctl

send "scan on\r"

sleep 10

send "quit \r"

expect eof

\r "Return/Enter 키 누르기"와 동일합니다. 실행파일을 만들어서 실행해보세요.

관련 정보