응답에 "연결 성공"이라는 문자열이 포함될 때까지 bash 스크립트에서 이 명령을 반복하려면 어떻게 해야 합니까?

응답에 "연결 성공"이라는 문자열이 포함될 때까지 bash 스크립트에서 이 명령을 반복하려면 어떻게 해야 합니까?

나는 이것으로 아무데도 갈 수 없습니다.

10번 반복하고 출력에 "Connection 성공적인" 문자열이 포함되어 있으면 중단되는 bash 스크립트를 만들고 싶습니다.

ret=$?then과 같은 것을 시도했지만 1이더라도 if [$ret -ne 0]계속 else 문이 나타납니다 .ret

이제 "연결 성공"이라는 단어를 찾으려고 노력하고 있지만 해당 구문을 사용하는 방법을 모르겠습니다.

그래서 나는 다음과 같은 것을 원합니다 :

for i in {1..10}
do
  ret=bluetoothctl connect 26:EE:F1:58:92:AF | grep "connection successful"

  if [$ret -ne ""]; then
    break
  fi
done

하지만 분명히 올바른 구문을 사용하면$ret=bluetoothctl connect 26:EE:F1:58:92:AF | grep "connection successful"

어떤 도움이라도 대단히 감사하겠습니다.

답변1

grep일부 텍스트가 패턴과 일치하는지 테스트하려는 경우 출력을 저장할 필요가 거의 없습니다. 대신 옵션을 grep사용하여 호출 -q하고 종료 상태에 따라 조치를 취하세요.

#!/bin/sh

tries=10

while [ "$tries" -gt 0 ]; do
    if bluetoothctl connect '26:EE:F1:58:92:AF' | grep -q 'connection successful'
    then
        break
    fi

    tries=$(( tries - 1 ))
done

if [ "$tries" -eq 0 ]; then
    echo 'failed to connect' >&2
    exit 1
fi

실패 및 성공 시 정상적인 종료 상태가 반환되는 경우 루프의 - 문이 bluetoothctl필요하지 않으며 다음과 같이 단축 grep할 수 있습니다 .if

if bluetoothctl connect '26:EE:F1:58:92:AF' >/dev/null
then
    break
fi

실제로 bluetoothctl루프 조건을 일부로 포함할 수도 있습니다( 여기에 표시된 것처럼 for루프에서 루프 사용으로 전환한다고 가정).while

#!/bin/sh

tries=10

while [ "$tries" -gt 0 ] && ! bluetoothctl connect '26:EE:F1:58:92:AF'
do
    tries=$(( tries - 1 ))
done >/dev/null

if [ "$tries" -eq 0 ]; then
    echo 'failed to connect' >&2
    exit 1
fi

사용을 고려해보세요https://www.shellcheck.net쉘 스크립트의 구문을 확인하십시오. 문제의 스크립트에 대해 테스트에는 다음 공백이 필요하다고 명시되어 있습니다 [ ... ].

  if [$ret -ne ""]; then
  ^-- SC1009 (info): The mentioned syntax error was in this if expression.
     ^-- SC1035 (error): You need a space after the [ and before the ].
     ^-- SC1073 (error): Couldn't parse this test expression. Fix to allow more checks.
                  ^-- SC1020 (error): You need a space before the ].
                  ^-- SC1072 (error): Missing space before ]. Fix any mentioned problems and try again.

비어 있지 않은 문자열에 대한 테스트는 [ -n "$ret" ]또는 를 사용하여 수행됩니다 [ "$ret" != "" ]. 이는-ne산수시험.

또한 파이프의 출력을 ret. 당신이 사용할 계획은

ret=$( bluetoothctl ... | grep ... )

답변2

Kusalananda는 코드를 개선하는 방법에 대한 팁을 제공하지만 정확히 무엇을 잘못하고 있는지 설명하지는 않습니다. 복습 해보자:

ret=$?나는 then 과 같은 것을 시도했지만 if [$ret -ne 0]ret가 1임에도 불구하고 여전히 else 문을 얻습니다.

[은 명령이므로 명령과 인수 사이에 공백을 넣어야 합니다. 그렇지 않으면 인수가 명령 이름의 일부로 이해됩니다. ret로 설정 하면 1bash는 오류를 인쇄해야 하며 [1: command not found오류 if에 대해서는 falsy가 표시되어야 합니다. 다시 말하지만, [마지막 매개변수는 필수 이지만 ]그렇지 0]않습니다. 거기에도 공간이 필요합니다.

당신이 원하는 것은 :

if [ "$ret" -ne 0 ]

다음 부분:

ret=bluetoothctl connect 26:EE:F1:58:92:AF | grep "connection successful"

여기서 수행하는 작업은 명령(존재하지 않을 수 있음) 에 값이 있는 환경 변수를 connect 26:EE:F1:58:92:AF | grep "connection successful"제공하는 동안 파이프라인을 실행하는 것입니다 .connectretbluetoothctl

출력을 수집하려면 명령을 다음으로 묶어야 합니다 $().

  ret="$(bluetoothctl connect 26:EE:F1:58:92:AF | grep "connection successful")"

이에:

  if [$ret -ne ""]; then

공백 누락과 동일한 문제가 있지만 더 깊이 이해하면 기본적으로 대부분의 항목은 bash에서 암시적으로 문자열이며 따옴표는 대부분 확장의 일부 세부 사항을 제어하는 ​​것 외에 더 명시적인 방법일 뿐이라는 것입니다. 즉, [$ret -ne ""]다음과 거의 정확하게 계산됩니다.

[$ret -ne ]
[$ret -ne ""''""'']
"["$ret "-ne" """]"
"["$ret"" "-ne""""" """]"""

비어 있으면 $ret와 같습니다 [ -ne ]. 비어 있지 않은 문자열인지 확인하기 위해 확인되는 인수(무시 됨 ]) 가 하나만 있기 때문에 true로 평가됩니다.[-ne

$ret그와 유사한 다른 것이라면 따옴표 foo bar baz누락으로 인해 토큰화되고 [foo bar baz -ne ]4개의 인수(포함)를 취하고 ]bash가 command를 찾을 수 없기 때문에 false인 command를 얻게 됩니다 [foo. $retlike를 인용하면 2개의 인수(포함)를 가지며 bash가 명령을 찾을 수 없기 때문에 false가 되는 ["$ret" -ne ""]동등한 결과를 얻게 됩니다 ."[foo bar baz" -ne ]][foo bar baz

여기서 저지르는 또 다른 실수는 -ne특히 수치 비교를 위해 를 사용하는 것입니다. 공백과 따옴표 문제를 해결하더라도 bash는 오류를 발생시킵니다 integer expression expected. 당신이 원하는 것은 !=문자열 비교를 위한 것입니다.

이러한 모든 문제를 요약하고 해결하려면 다음이 필요합니다.

if [ "$ret" != "" ]; then

다음과 같이 쓸 수도 있습니다.

if [ -n "$ret" ]; then

또는

if [ "$ret" ]; then

관련 정보