긴 이야기 짧게
나는 이것에 대해 몇 가지 조사를 했고 당신은 내가 한 일을 볼 수 있습니다더 자세한 내용과 나의 시도부분.
내 명령은
date && echo "hi 1" && echo "1/0" | bc >/dev/null 2>&1 && echo "hi 2" && date +'%s'
내 예상/원하는 출력은 다음과 같습니다.
Tue, Nov 17, 2020 3:13:49 PM
hi 1
그리고 멈추게 하세요. 내 생각은 표현식의 " echo
/ bc
" 부분입니다 (작업 우선 순위가 괄호로 표시된다고 가정)
<part-before>
( echo "1/0" | bc >/dev/null 2>&1
) &&
<part-after>
<part-after>
목적이 달성되지 않도록 해야 합니다 . 그러나 내실제출력( date
현재 명령 사용)은 다음과 같습니다.
Tue, Nov 17, 2020 3:13:49 PM
hi 1
hi 2
1605651229
질문: 아무것도 출력하지 않고 실패하고 0으로 나누기 문제에서 멈추게 하려면 어떻게 해야 합니까?
(이후의 내용은 더 자세한 내용을 제공하기 위한 것입니다.)
빠른 참고 사항: 리디렉션이 없더라도 0으로 나누는 데 실패해도 체인 &&
, 즉 단락된 AND 연산자 체인이 중지되지 않습니다. 보다,
bballdave025@MACHINE ~
$ date && echo "hi 1" && echo "1/0" | bc && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:14:47 PM
hi 1
Runtime error (func=(main), adr=3): Divide by zero
hi 2
1605651287
bballdave025@MACHINE ~
$
bc
나는 주로 $((
))
아래와 같은 bash-ism을 피하기 위해 이 방법을 사용하고 싶습니다 . (bash-isms에 대해 말하자면, 노력해도 &>/dev/null
아무 것도 바뀌지 않았습니다.) 아래 예와 같은 것을 얻고 싶습니다.
bballdave025@MACHINE ~
$ date && echo "hi 1" && echo "$((1/0))" >/dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:15:17 PM
hi 1
-bash: 1/0: division by 0 (error token is "0")
bballdave025@MACHINE ~
$
하지만 나는 오류를 원하지 않습니다. 0으로 나눈 잘못된 결과가 출력되지 않는 한, 즉 -ed가 없으면 echo
오류를 제거할 수 있습니다 (이는 리디렉션의 목적을 무너뜨리고stdout
stderr
### NOT WHAT I WANT, other than what is output ###
bballdave025@MACHINE ~
$ date && echo "hi 1" && ((1/0)) >/dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:15:44 PM
hi 1
bballdave025@MACHINE ~
### NOT WHAT I WANT, other than what is output. ###
좀 더 이론적인 설명은 다음과 같습니다.무엇에 0(영)을 전달하고 있습니다 &&
. 무엇입니까?
리디렉션은 명령이 아닙니다.
지금은 어디를 봐야할지 모르겠습니다.
편집하다: 좀 더 조사해 봤습니다. 두 가지 점을 추가하고 싶습니다.
여러 소스를 찾았습니다.그들 중 하나(보관됨) 이것이 핵심일 수 있다고 생각하지만 그것이 어떻게 적용되는지 여전히 이해하지 못합니다.다른(보관됨) 단락에 대해 설명하는데, 이것이 중요할 수 있다고 생각됩니다.
>/dev/null
실수로 로 교체했을 때 이상한 동작을 발견하여>dev/null
버그가 발생했습니다.뒤쪽에문제를 0으로 나눕니다. 이것이 내가 보는 것입니다.
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" | bc >dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:41:39 PM
hi 1
-bash: dev/null: No such file or directory
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" | bc >dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:41:48 PM
hi 1
-bash: dev/null: No such file or directory
bballdave025@MACHINE ~
$
솔직히 이것은 특히 첫 번째, 아마도 핵심 소스를 고려하면 더욱 혼란스럽습니다.
더 자세한 내용과 나의 시도
나는 더 큰 실행 파일을 포함하는 더 긴 체인을 구축하기 위해 &&
체인과 리디렉션을 이해하려고 노력하고 있습니다. /dev/null
나도 알고 싶다명령 목록 구분 기호(보관됨) 일반적으로 말하면 이러한 실행 파일이 어떻게 함께 작동하는지에 관계없이 여기서 무슨 일이 일어나고 있는지 정말로 이해하고 싶습니다 &&
.
나는 실제 예제로 넘어가기 전에 이 장난감 예제를 작업해 왔습니다. 나는 문제를 찾을 수 있는지 확인하기 위해 "뒤로 작업"하려고 노력해 왔습니다. 아마도 이것은 문제를 해결하는 데 유용할 것입니다.
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" | bc >/dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:16:41 PM
hi 1
hi 2
1605651401
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" | bc >/dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:16:52 PM
hi 1
hi 2
1605651412
## LET'S SEE WHAT GETS SENT TO /dev/null
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" | bc >abc 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:17:06 PM
hi 1
hi 2
1605651426
bballdave025@MACHINE ~
$ cat abc
1
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" | bc >abc 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:17:18 PM
hi 1
hi 2
1605651438
bballdave025@MACHINE ~
$ cat abc
Runtime error (func=(main), adr=3): Divide by zero
## LET'S TRY GIVING IT ANOTHER ERROR RIGHT AFTER
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" | bc >dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:24:35 PM
hi 1
-bash: dev/null: No such file or directory
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" | bc >dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:25:00 PM
hi 1
-bash: dev/null: No such file or directory
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" | bc >abc 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:25:14 PM
hi 1
hi 2
1605651914
bballdave025@MACHINE ~
$ cat abc
1
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" | bc >abc 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:25:24 PM
hi 1
hi 2
1605651924
bballdave025@MACHINE ~
$ cat abc
Runtime error (func=(main), adr=3): Divide by zero
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" | bc >abc/def 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:25:41 PM
hi 1
-bash: abc/def: Not a directory
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" | bc >abc/def 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:25:46 PM
hi 1
-bash: abc/def: Not a directory
## GO BACK WITHOUT `bc` and without redirection
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" >/dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:29:03 PM
hi 1
hi 2
1605652143
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" >/dev/null 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:29:12 PM
hi 1
hi 2
1605652152
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" >abc 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:29:21 PM
hi 1
hi 2
1605652161
bballdave025@MACHINE ~
$ cat abc
1/1
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" >abc 2>&1 && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:29:29 PM
hi 1
hi 2
1605652169
bballdave025@MACHINE ~
$ cat abc
1/0
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$b" && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:30:09 PM
hi 1
1/1
hi 2
1605652209
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "$a/$c" && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:30:14 PM
hi 1
1/0
hi 2
1605652214
bballdave025@MACHINE ~
$ a=1; b=1; c=0; date && echo "hi 1" && echo "hi 2" && date +'%s'
Tue, Nov 17, 2020 3:30:26 PM
hi 1
hi 2
1605652226
bballdave025@MACHINE ~
$
답변1
리디렉션이 없더라도 0으로 나누는 데 실패하더라도 "and" 연산자의 단락 체인인 && 체인이 중지되지 않습니다.
GNU BC:
$ echo "1/0" | bc
Runtime error (func=(main), adr=3): Divide by zero
$ echo $?
0
바쁜 상자:
$ echo "1/0" | busybox bc
bc: divide by zero
$ echo $?
1
이름
bc - 임의 정밀도 산술 언어
종료 상태
다음 종료 값이 반환되어야 합니다.
0 - 모든 입력 파일이 성공적으로 처리되었습니다.
지정되지 않음 - 오류가 발생했습니다.
근거
오류 조건의 종료 상태는 여러 가지 이유로 지정되지 않습니다.
- bc 유틸리티는 대화형 상황과 비대화형 상황 모두에서 사용할 수 있습니다. 두 가지 목적 모두에 서로 다른 종료 코드가 적합할 수 있습니다.
- 0이 아닌 종료가 언제 제공되어야 하는지는 명확하지 않습니다. 0으로 나누기, 정의되지 않은 함수 및 구문 오류가 모두 가능합니다.
- 종료 상태가 어떤 용도로 사용되는지는 확실하지 않습니다.
BC는 0으로 나누는 것이 잘못된 종료 상태를 반환할 가치가 없다고 생각하기 때문에 체인이 끊어지지 않습니다.
그러나 GNU bc는 입력 파일을 읽을 수 없는 경우 잘못된 종료 상태를 반환합니다.
나는 주로 나중에 $(( ))와 같은 bash-isms를 피하기 위해 bc 방법을 사용하고 싶습니다.
$(( ))
바시즘이 아니라 바시즘의 일부POSIX 쉘 언어(산술 확장).
&&
여기서의 맥락이 무엇인지, 0으로 나누는 것이 조건 및 체인과 어떻게 관련되는지, 궁극적으로 무엇을 하려는지 잘 모르므 로 조언을 제공하기가 어렵습니다.
0으로 나누기를 감지하는 또 다른 방법은 나누기를 먼저 시도하기 전에 나누기가 0인지 확인하는 것입니다.
답변2
이는 XY 문제, 파이프, 출력 및 분할 문제가 혼합된 것입니다. 답변해야 할 "단일" 질문이 있는 것 같지는 않지만 이를 명확히 하려고 노력할 것입니다.
쉘 언어
그룹
echo "before" && echo inside1 && echo inside2 && echo "after"
여러 명령문을 그룹화하는 방법은 괄호나 중괄호를 사용하는 것입니다.
echo "before" && ( echo inside1 && echo inside2 ) && echo "after"
echo "before" && { echo inside1 && echo inside2; } && echo "after"
()
서브쉘에서 실행되며 { }
단순히 현재 환경에서 목록을 형성합니다. 둘 다 해당 섹션의 출력을 리디렉션하는 데 사용할 수 있습니다.
echo "before" && ( echo inside1 && echo inside2 ) > /dev/null && echo "after"
echo "before" && { echo inside1 && echo inside2; } > /dev/null && echo "after"
반환 값
각 명령은 완료 후 값을 반환합니다. $?
사용하실 수 있도록 저장되어 있습니다.echo $?
실행 직후.
성공을 나타내려면 0을 반환하고 실패를 나타내려면 0이 아닌 값을 반환하는 것이 규칙입니다. 어떤 계획이든 성공으로 간주될 수 있습니다. and &&
및 또는 ||
쉘 연산자는 이 개념을 활용합니다. 또한 항상 0(성공)과 0이 아닌 값(실패)을 반환하는 true
and 라는 편리한 유틸리티도 있습니다 .false
if true && false; then
echo Yes
else
echo No
fi
series 를 연결하면 &&
연산자의 오른쪽은 왼쪽이 성공을 반환하는 경우에만 실행됩니다.
photos
예를 들어, 이라는 폴더를 만들고 모든 파일을 그 폴더로 이동할 수 있습니다 .
먼저 사용해 볼 수 있습니다.
mv *.jpg photos
그러나 사진이 하나만 있고 photos
폴더가 없으면 사진 이름이 로 변경됩니다 photos
.
폴더가 성공적으로 생성되면 해당 폴더를 사용하여 이미지를 이동할 수만 있습니다 &&
.
mkdir photos && mv *.jpg photos
mkdir
실패 하면 mv
실행되지 않습니다.
mkdir
이는 실패 시 0이 아닌 값이 반환되기 때문입니다 .
그러나 폴더가 photos
이미 존재하는 경우 mkdir
오류 조건도 반환됩니다(폴더를 만들 수 없습니다).
따라서 더 복잡한 검사는 다음과 같습니다.
( test -d photos || mkdir photos ) && mv *.jpg photos/
photos가 이미 디렉토리인 경우 디렉토리를 생성하려고 시도하지 않고 대신 이미지 이동으로 이동합니다. 그러나 photos
디렉터리는 아니지만 생성할 수 있으면 성공하고 사진을 이동합니다.
사진이 폴더(또는 폴더에 대한 심볼릭 링크)가 아니고 생성되지 않은 경우 왼쪽 부분이 &&
실패하고 사진이 이동하지 않습니다.
참고 사항: 이 특정 예의 경우 더 간단한 것을 사용할 수 있습니다 mkdir -p photos && mv *.jpg photos/
. -p
플래그를 사용하면 mkdir이 중간 폴더를 생성하고 폴더가 이미 존재하는 경우 종료되지 않지만 덜 설득력이 있기 때문입니다.
관로
파이프가 있는 경우 기본적으로 파이프의 반환 값은 가장 오른쪽 명령 중 하나입니다. 실행하면
command1 | command2 | command3
전체 파이프라인의 반환 값은 의 반환 값이 됩니다 command3
. command1
또는 command2
0이 아닌 값을 반환하는 것은 중요하지 않습니다. pipefail
반환 값이 다음 중 하나가 되도록 옵션을 설정하여 이를 변경할 수 있습니다.0이 아닌 값을 반환하는 파이프라인의 가장 오른쪽 명령.
0으로 나누기
귀하의 경우 0으로 나누기 시도에 대한 진단을 화면에 제공하더라도 0 코드가 실제로 반환되기 echo 1/0 | bc
때문에 파이프라인이 중지되지 않습니다 .bc
$((1/0))
확장 프로그램에서 오류가 발생하기 때문에 직접 실행하는 데 문제가 있습니다. 새로운 셸 프로세스로 래핑할 수 있습니다.
echo hi1 && bash -c 'echo $((1/0))' 2> /dev/null && echo hi2
아니면 그냥 서브쉘일 수도 있어요
echo hi1 && ( echo $((1/0))' ) 2> /dev/null && echo hi2
실제로 기본적인 솔루션이 있습니다.제수가 0인지 확인. 예를 들어:
division() {
if [ "$2" -eq 0 ]; then
return 1
fi
echo "$(( $1 / $2 ))"
}
echo hi1 && division 1 0 && echo hi2
함수를 사용하여 비슷한 작업을 수행할 수도 있습니다 bc
(그러나 아무것도 출력하지 않는 대신 0을 출력합니다).
define division(x,y) {
if (y == 0) return;
return x/y;
}
division(1,0)