이렇게 간단한 "if"가 작동하지 않는 이유는 무엇입니까?

이렇게 간단한 "if"가 작동하지 않는 이유는 무엇입니까?

이것은 내 스크립트입니다.

if [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] && [[ "$1" == "Decrypt" ]] || [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] && [[ "$1" == "Encrypt" ]] 
then
    key=aNXlye1tGbd0uP
else
    if [ -z "$key" ]
    then
        key="$2"
    fi
fi

두 번째 매개변수를 찾아 전위를 제거한 .two다음 와 비교하고, load그렇다면 로 load설정해야 합니다 . 그러나 이것은 작동하지 않습니다. 실행해 보면 이런 느낌이에요.keyaNXlye1tGbd0uP

pskey Decrypt load (some string)

이것은 다음의 출력입니다 bash -x.

++ echo load
++ sed s/.two//g
+ [[ load == \l\o\a\d ]]
+ [[ Decrypt == \D\e\c\r\y\p\t ]]
+ [[ Decrypt == \E\n\c\r\y\p\t ]]
+ '[' -z '' ']'
+ key=load

그러나 뒤에 오는 것을 제거하면 [[ "$1" == "Decrypt" ]]작동합니다. 그 라인에 문제가 있나요?

답변1

내가 올바르게 이해했다면 다음과 같은 것을 찾고 있습니다.

if [[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" == "Decrypt" ]] || 
   [[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" == "Encrypt" ]]
then
    ...
fi

다음과 같이 모든 것을 단순화할 수도 있습니다.

 if [[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" =~ (De|En)crypt ]]; then ...

답변2

terdon의 진술은 "이것은 '단순함'과는 거리가 멀습니다 if." ~처럼존 쿠겔만(John Kugelman)은 다음과 같이 지적했다., 동일한 우선순위를 가지며 왼쪽에서 오른쪽으로 처리됩니다  &&.||BinaryZebra가 이 아이디어를 제안했습니다.부울 표현식을 계단식 if명령문으로 변환합니다. 나는 "단순화"하려고 노력한다

A && B인 경우 ||
그 다음에
        결과=0
기타
        결과=1
필리핀 제도

만약
그 다음에
        B라면
        그 다음에
                만약 D                                        
                그 다음에
                        결과=0
                기타
                        결과=1
                필리핀 제도
        기타
                만약 C
                그 다음에
                        만약 D
                        그 다음에
                                결과=0
                        기타
                                결과=1
                        필리핀 제도
                기타
                        결과=1
                필리핀 제도
        필리핀 제도
기타
        만약 C
        그 다음에
                만약 D
                그 다음에
                        결과=0
                기타
                        결과=1
                필리핀 제도
        기타
                결과=1
        필리핀 제도
필리핀 제도

아주 멀리간단하게 시작하세요. 위에서 알 수 있듯이 작동하지 않는 이유는 (표시된 줄에서) A와 B가 모두 true인 경우 D( [[ "$1" == "Encrypt" ]])를 계속 테스트하기 때문입니다.

BinaryZebra가 보여주지만 언급하지는 않는 것처럼,할 수 있는예를 들어 sh/bash 스크립트에 수학적 표기법을 사용하면 됩니다.

if (A && B) ||
그 다음에

또는 약간 단순화된 코드 버전에서는

만약에([["$2"=="로드"]] && [["$1"=="해독"]])  ||  ([["$2"=="로드 중"]] && [["$1"=="암호화됨"]])
그 다음에

그 특징은 괄호 안의 코드가 서브쉘에서 실행된다는 것입니다. 이것이 문제라면 중괄호를 대신 사용할 수 있습니다.

만약에{[["$2"=="로드"]] && [["$1"=="해독"]];  ||  {[["$2"=="로드 중"]] && [["$1"=="암호화됨"]];
그 다음에

앞에 하나 (선택적으로 공백으로 구분) ;가 있어야 하며 앞 , 뒤, 뒤에 공백이 있어야 합니다 .}{}

물론 다른 답변에서 제안한 기술을 사용해야 합니다.단순화하다귀하의 테스트입니다.아니요동일한 테스트를 두 번 수행합니다 $2.

관련된:파이프 및 리디렉션과 분리, 조인 등에 대한 바인딩 우선 순위는 무엇입니까?그리고"if"가 불필요한 경우는 언제입니까?

답변3

코드에서:

if    [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] &&
      [[ "$1" == "Decrypt" ]]                          ||
      [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] &&
      [[ "$1" == "Encrypt" ]] 

sed 호출은 다음과 같이 단순화될 수 있습니다. ${2%?two}if 대체는 변수 끝에 있습니다 $2. 점(.)은 패턴의 물음표(?)에 해당하는 sed의 "모든 문자"를 의미한다는 점을 이해하시기 바랍니다(@terdon에게 감사드립니다). 모든 항목을 교체해야 하는 경우 다음을 .two사용해야 합니다 "${2//?two}". 그런 다음 다음과 같은 더 짧은 버전을 얻습니다.

if [[ "${2//?two}" == "load" ]]  &&  [[ "$1" == "Decrypt" ]]  ||
   [[ "${2//?two}" == "load" ]]  &&  [[ "$1" == "Encrypt" ]] 

이게 뭐 하는 거야 if A && B || C && D?

A가 참인 경우(로드 = 로드) B가 실행됩니다. B가 true(Decrypt = Decrypt)인 경우
다음 구문(C)을 건너뛰고 D(Decrypt = Encrypt)를 실행합니다. 결과(실행된 마지막 명령)는 값입니다. 그럼 실행해...||

false
else

나는 당신이 if ( A && B ) || ( C && D ), as 가 와 A동일 C하고 와 정확히 같다는 것을 의미한다고 생각합니다 if ( A && B ) || ( A && D ). 이는 단순화될 수 있습니다(사용하여재산을 분배하다) 도착하다
if A && ( B || D ):

if      [[ "${2//?two}" == "load" ]] &&
      ( [[ "$1" == "Decrypt" ]]   ||  [[ "$1" == "Encrypt" ]]  );
then
      key=aNXlye1tGbd0uP
else
      if    [ -z "$key" ]
      then  key="$2"
      fi
fi

"$key"에 대한 테스트는 -z간단한 확장으로 축소될 수 있습니다: key="${key:-$2}"

그리고 아마도 다음과 같이 더 읽기 쉬울 것입니다(IMO).

if A; then
      if   B || D; then

번역하면 이렇습니다.

if           [[ "${2//?two}" == "load" ]]
then   if    [[ "$1" == "Decrypt" ]]   ||  [[ "$1" == "Encrypt" ]]
       then  key=aNXlye1tGbd0u
       else  key="${key:-$2}"
       fi
else         key="${key:-$2}"
fi

또는 @terdon의 아이디어를 사용하여 다음과 같이 작성할 수 있습니다.

if           [[ "${2//?two}" == "load" ]] &&
             [[ "$1" =~ (De|En)crypt ]]
then         key=aNXlye1tGbd0u
else         key="${key:-$2}"
fi

이것도 동일합니다.

if       [[  ( "${2//?two}" == "load" ) &&
             ( "$1" =~ (De|En)crypt )
         ]]
then         key=aNXlye1tGbd0u
else         key="${key:-$2}"
fi

괄호는 꼭 필요한 것은 아니지만 [[테스트 내부에서 공백(탭, 공백, 줄 바꿈) 및 괄호를 추가하여 테스트에 구조를 제공할 수 있다는 아이디어를 강화하기 위해 추가되었습니다. 이것은 테스트에서 다르게 작동했습니다 [.

답변4

첫 번째:

[[ $1:$2 =~ ^(En|De)crypt:(.two)*load(.two)*$ ]] && echo conditions met

그러나 if부울 논리는 반대입니다.

#sed    #En=$1   #De=$1
true  && false || true    # passes your logic
true  && true  || NA      # passes your logic
false && NA    || false   # fails  your logic
false && NA    || true    # fails  your logic

두 번째 것은 &&요인이 아니기 때문에 여기서는 생략됩니다. 그 결과는 항상 첫 번째 것과 동일합니다. 이 논리 사슬에서 그것은 쓸모없는 것입니다.

이는 그다지 효과적이지 않습니다. 실패한 사례로 인해 귀하의 진술이 깨집니다. 첫 번째 테스트가 거짓인 경우에는 (De|En)crypt 테스트 대신 OR 반환을 수행합니다. 사실 첫 번째는 쇼트 때문에 발생하지도 않습니다.반품. 따라서 먼저 OR을 수행하고 실제로 테스트해야 할 때까지 비용이 많이 드는 명령 대체를 지연하여 단락을 활용해야 합니다.

#En=$1  #De=$1   #sed
false || false && NA
false || true  && false
false || true  && true
true  || NA    && false
true  || NA    && true

이 모든 것이 논리를 통과합니다. 처음 두 문이 모두 거짓이면 명령 대체가 시도되지 않습니다.

이는 case및 다음 을 사용하여 이식 가능합니다 expr.

case  ${2%oad*}:${1%crypt}  in
(:${key:=$2}*|*ad*|*:"$1")  ;;
(*l:De|*l:En)  expr " $2" :  \
" \(\(.two\)*\(load\)*\)*$" &&
     key=aNXlye1tGbd0uP
esac >/dev/null   

그리고 if:

if   [ Encrypt = "$1" -o Decrypt = "$1" ] &&
     expr " $2" : " \(.two\)*load\(.two\)*$"
then key=$newkey
else key=${key:-$2}
fi   >/dev/null

그냥 expr&&||, if그것은 당신에게 별로 도움이 되지 않기 때문에:

expr   > /dev/null       \
 "${#1} ${1%crypt}  $2" :\
 "7 \(\(De\)*\(En\)*\) ""\
 \(.two\)*load\(.two\)*$" &&
key=$newkey || key=${key:-$2}

아마도 다음과 같은 것들이 있을 것입니다 grep:

grep -xqE '(En|De)crypt:(.two)*load(.two)*' \
<<VAR &&   key=$newkey || key=${key:-$2}
${1##*:*}:$2
VAR

관련 정보