문자열이 다음으로 시작하는지 또는 무엇인가를 포함하는지 확인하는 함수를 작성하세요.

문자열이 다음으로 시작하는지 또는 무엇인가를 포함하는지 확인하는 함수를 작성하세요.

var주어진 변수(예: )가 주어진 문자열 목록에 있는 단어 중 하나로 시작하는지 확인하는 함수를 작성하고 싶습니다 . 이 목록은 변경되지 않습니다.

인스턴스화하기 위해 , 또는 로 var시작하는지 확인하고 싶다고 가정해 보겠습니다 .aaabc3@3

var또한 문자가 포함되어 있는지 확인하고 싶습니다 >.

이 함수를 이라고 해보자 check_func. 내 의도 된 사용법은 다음과 같습니다

if check_func "$var"; then
    do stuff
fi

aardvark예를 들어 , abcdef, [email protected]및 에 대해 "작업을 수행"해야 합니다 12>5.


나는 본 적이이 SO 질문사용자가 저작물의 일부를 제공하는 경우:

beginswith() { case $2 in "$1"*) true;; *) false;; esac; }

내 생각은 위에서 언급한 목록을 반복하고 이 기능을 사용하는 것입니다. 나의 어려움은 이 작업을 수행하기 위해 종료(또는 복귀를 대체하는 모든 것)가 어떻게 수행되어야 하는지 정확히 이해하지 못하는 데 있습니다.

답변1

check_prefixes () {
    value=$1

    for prefix in aa abc 3@3; do
        case $value in
            "$prefix"*) return 0
        esac
    done

    return 1
}

check_contains_gt () {
    value=$1

    case $value in
        *">"*) return 0
    esac

    return 1
}

var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
    printf '"%s" contains ">" and starts with one of the prefixes\n' "$var"
fi

테스트를 두 가지 기능으로 나누었습니다. case ... esac이것이 확인되는 즉시 성공(0)을 사용 하고 반환합니다. 일치하는 항목이 없으면 실패(1)가 반환됩니다.

접두사 목록을 보다 동적 목록으로 만들려면 첫 번째 함수를 다음과 같이 작성할 수 있습니다.

check_prefixes () {
    value=$1
    shift

    for prefix do
        case $value in
            "$prefix"*) return 0
        esac
    done

    return 1
}

(검사할 값은 첫 번째 인수입니다. 이를 함수에 대한 인수 목록에 저장 value한 다음 제외합니다. 그런 다음 나머지 인수를 반복합니다.) 그런 다음 다음과 같이 호출합니다.shift

check_prefixes "$var" aa abc 3@3

두 번째 함수도 비슷한 방식으로 다음과 같이 변경될 수 있습니다.

check_contains () {
    value=$1
    shift

    case $value in
        *"$1"*) return 0
    esac

    return 1
}

(임의의 하위 문자열을 확인하기 위해) 또는

check_contains_oneof () {
    value=$1
    shift

    for substring do
        case $value in
            *"$substring"*) return 0
        esac
    done

    return 1
}

(여러 하위 문자열 중 하나를 확인하기 위해)

답변2

배쉬의 경우:

정규 표현식의 속성을 사용하면 아무것도 없이 작성할 수 start있습니다 .^contain

확인할 정규식 목록시작또는 aa abc3@3포함 >이다:

^aa ^abc ^3@3 >

그걸로 만들어제대로인용된 목록을 작성하고 bash에 정규식( )을 사용하도록 요청합니다 =~.

check_func() {
               matched=1
               for test_regex in '^aa' '^abc' '^3@3' '>'; do
                   if [[ $var =~ $test_regex ]] ; then
                       matched=0
                       break 
                   fi
               done
               return "$matched"
              }

var='aaIsAMatch'
if check_func; then
    echo "A match was found"
fi

이 함수는 일치 항목 목록과 var의 이름을 하드 코딩했습니다.

배열 변수의 정규식 목록과 첫 번째 인수에 대해 테스트할 값 제공:

check_func() {
               local matched; matched=1
               for t in "${test_regex[@]}"; do
                   [[ $1 =~ $t ]] && { matched=0; break; } 
               done
               return "$matched"
              }


test_regex=('^aa' '^abc' '^3@3' '>')

if check_func 'aaIsAMatch'; then
    echo "A match was found"
fi

변수 이름(값 대신)을 첫 번째 인수로 사용하도록 함수를 더욱 개선할 수 있습니다.

포식스

posix 쉘에는 정규 표현식이 없고 테스트할 수 있는 유일한 방법은 Case 문이므로 Case 문을 사용해야 합니다. 안타깝게도 이전 쉘([사용 가능한 확장 글로브 없음][1])의 경우 모든 테스트를 수행하려면 루프를 반복해야 합니다. 그리고 글로브는 다음과 같아야 합니다.

'aa*' 'abc*' '3@3*' '*>*'

여러 glob에 대해 여러 입력 문자열을 테스트하는 스크립트 예:

check_func() { :
           matched=1
       value=$1; shift
           for t in "$@"; do
               case $value in $t) matched=0; #break;; esac
                  echo "matched $value with $t"
                  ;;
       esac
       done
           return "$matched"
         }


for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
        echo "========A match was found for \"$var\""
fi
done

귀하의 요청과 정확히 일치하는 간단한 버전의 함수:

check_func() { :
               matched=1
               value=$1; shift
                   for t in "$@"; do
                       case $value in $t) matched=0; break;; esac
                   done
               return "$matched"
             }

답변3

명령문이 수행하는 작업은 다음과 같습니다 case. 두 번째 매개변수를 함수( $2)에 가져옵니다. 패턴 "$1"*, 즉 함수에 대한 첫 번째 인수와 그 뒤에 아무 것도 일치하지 않으면 명령문을 실행 true하고 종료합니다 case. true아무것도 하지 않고 상태 0을 반환합니다. 그렇지 않고 일치하면 *, 즉 무엇이든 일치하면 명령문을 실행 false하고 종료합니다 case. false아무 것도 하지 않고 상태 1을 반환합니다. 따라서 case두 번째 매개 변수가 첫 번째 매개 변수로 시작하면 명령문의 상태는 0이고 그렇지 않으면 1입니다. 이것이 함수의 마지막(유일한) 명령문이므로 두 번째 매개변수가 첫 번째 매개변수로 시작하면 함수는 0을 반환하고 그렇지 않으면 1을 반환합니다.

if셸과 같은 조건문은 0을 반환하면 해당 명령문을 true로 간주하고 그렇지 않으면 false로 간주합니다. 따라서 값이 다음으로 시작 하면 if beginswith "$var" "string"; then echo yes; else echo no; fi인쇄되고 그렇지 않으면 인쇄됩니다 .yesvarstringno

이 함수를 작성하는 방법에는 여러 가지가 있습니다. 예를 들어 작성자는 and 대신 return 0or를 사용할 수 있습니다 . 이는 함수의 마지막 문이기 때문입니다. 함수가 작성된 방식을 사용하면 함수 매개변수( 및 )에 대한 참조를 작업하려는 문자열로 변경하기만 하면 함수에서 함수를 래핑하지 않고도 본문을 직접 사용할 수 있습니다 .return 1truefalse$1$2

여러 접두사를 허용하려면 루프에서 반복합니다. 일치하는 접두사를 찾으면 즉시 실제 상태(0)로 함수에서 반환됩니다. 일치하는 접두사가 없으면 거짓 상태(일반적으로 1)를 반환합니다.

# begins_with STRING PREFIX1 PREFIX2...
# Test if STRING starts with any of PREFIX1, PREFIX2, ...
begins_with () {
  string=$1
  shift
  for prefix in "$@"; do
    case "$string" in
      "$prefix"*) return 0;;
    esac
  done
  return 1
}

if begins_with "$var" 'aa' 'abc' '3@3'; then
  echo "The value starts with one of the permitted prefixes"
fi

접미사를 테스트하려면 *"$suffix"대신 패턴을 사용하십시오 "$prefix"*. 하위 문자열을 테스트하려면 를 사용하세요 *"$substring"*. 여기서는 큰따옴표가 필요합니다. 그렇지 않으면 변수가 패턴으로 해석됩니다. 예를 들어:

suffix='?'
case "$var" in
  *"$suffix") echo "The value of var ends with a question mark";; 
esac
case "$var" in
  *$suffix) echo "The value of var is not empty";; 
esac

답변4

질문에 대한 설명을 바탕으로 수정되었습니다. 이것은 덜 우아하고 (훨씬 덜 유연하지만) 다른 답변보다 더 컴팩트합니다.

check_func() {
        case "$1" in
            ( aa* | abc* | 3@3*  | *">"*)
                return 0
        esac
        return 1
}

aardvark, 및 abcdef에 대해 true를 반환합니다 . 그리고 물론 , 및 .[email protected]12>5aard>varkabc<def>ghi3@3>3

관련 정보