나는 이것으로 아무데도 갈 수 없습니다.
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
로 설정 하면 1
bash는 오류를 인쇄해야 하며 [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"
제공하는 동안 파이프라인을 실행하는 것입니다 .connect
ret
bluetoothctl
출력을 수집하려면 명령을 다음으로 묶어야 합니다 $()
.
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
. $ret
like를 인용하면 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