문자열에 대시 또는 회색 부분 문자열이 포함되어 있는지 확인하는 방법은 무엇입니까?

문자열에 대시 또는 회색 부분 문자열이 포함되어 있는지 확인하는 방법은 무엇입니까?

이것이 내가 시도하는 것입니다:

#!/bin/sh
contains() {
    if $(echo $1 | grep -c $2) ; then
        echo "0" # contains
    else
        echo "1" # not contains
    fi
}

myString=$1
mySubsting=$2

contains $myString '$mySubsting'

실행 예는 다음과 같습니다.

# sh ./myScript abcdef bc
./myTest: line 3: 0: command not found
1

편집하다:

원래 질문: Bourne Shell에서 문자열에 하위 문자열이 포함되어 있는지 확인하는 방법은 무엇입니까?

이것이 내가 시도하는 것입니다:

  #!/bin/sh
  if echo $1 | grep -q $2
  then
    echo "0"
  else
    echo "1"
  fi

실행 예는 다음과 같습니다.

$ sh ./myTest "$(systemctl status ntp)" "Active: active"
grep: active: No such file or directory
1

문자열에 다른 문자열이 포함되어 있는지 올바르게 확인하는 방법은 무엇입니까?

답변1

함수를 포함하는 이식 가능한(dash, bash, ksh 등) 스크립트:

#!/bin/sh

contains() {  if    [ "$1" ] &&            # Is there a source string.
                    [ "$2" ] &&            # Is there a substring.
                    [ -z "${1##*"$2"*}" ]; # Test substring in source.
              then  echo 0;                # Print a "0" for a match.
              else  echo 1;                # Print a "1" if no match.
              fi;
            }

contains "$1" "$2"

여기서 0은 "포함"(참값)을 의미합니다.

이는 다음과 같이 테스트됩니다.

 $ contains "test a simple line" simpl
 1

 $ contains "One sentence" "No more"
 0

답변2

Bourne 쉘에는 이러한 목적을 위한 구성이 있습니다. 이것은 현대의 것과 동일합니다 sh(이것은 Bourne 쉘에서 지원되지 않는 사용 중인 것과 더 비슷해 보입니다 $(...). Bourne 쉘인 경우 다른 오류가 발생합니다).

case $1 in
  *"$2"*) printf '"%s" is in "%s"\n' "$2" "$1"
esac

을 사용하려는 경우 grep다음과 같습니다.

if printf '%s\n' "$1" | grep -Fqe "$2"; then
  printf '"%s" is in "%s"\n' "$2" "$1"
fi

또는

if grep -Fqe "$2" << EOF
$1
EOF
then
  printf '"%s" is in "%s"\n' "$2" "$1"
fi

$2그러나 개행 문자가 포함되지 않은 경우에만 제대로 작동합니다.

그럼에도 불구하고 대부분의 매개변수 확장을 인용해야 합니다. 필요하지 않은 유일한 곳은 저 위지만 case $1, 그래도 case "$1"아프지는 않습니다.

코드에 대한 몇 가지 참고 사항:

  1. echo임의의 문자열 과 함께 사용할 수 없습니다.. 여기서는 구현에 따라 echo또는 같은 값에 대해서는 실패합니다.$1-nfoo\bar
  2. 셸에서 인용되지 않은 매개변수 확장은 매우 특별한 의미를 갖습니다.. 당신은 그렇게하고 싶지 않습니다. 예를 들어, grep -c $2또는 같은 값을 사용해 보세요 .$2*root /etc/passwd
  3. grep없이는 -F정규식 일치에 사용됩니다. -F문자열(하위 문자열) 검색(과거)을 수정 해야 fgrep하지만 $2여러 줄이 포함된 경우 다시 grep -F검색하려는 경우어느입력에서 이러한 줄의 내용은 문자열이 아닌 or 를 grep -F $'a\nb'찾습니다 .ab$'a\nb'
  4. 에서 grep -c $2로 시작하면 의 내용은 $2옵션으로 처리됩니다 -. 당신은 이 상황을 원 grep -c -e "$2"하거나 grep -c -- "$2"피합니다.
  5. 부울 조건을 보고하기 위해 표준 출력 대신 종료 상태를 사용하려고 합니다. 스크립트에서 exit( exit 0true의 경우 exit 1(또는 0이 아닌 숫자, 120보다 큰 값은 피함)의 경우 false)를 사용합니다. 기능의 경우 return대신 사용하세요. 스크립트와 함수 모두 마지막 명령 실행 상태를 반환합니다.
  6. $(cmd) 확장하다후행 줄 바꿈을 뺀 출력 cmd(그리고 따옴표가 다시 누락되어 여기에서 분할+glob을 거치는 것)입니다. 따라서 cmd출력이 로 확장 0\n되면 run 은 이라는 명령을 실행하려고 시도합니다 . 출력을 종료 상태로 변환하려면 (부울로 사용할 수 있음) 종료 코드로 출력으로 종료되는 서브셸이 시작됩니다 .$(cmd)0$(cmd)0cmd(exit "$(cmd)")cmd
  7. grep -c발생 횟수를 계산합니다. 여기에서는 전체 개수가 필요하지 않으며, 검색되었는지(일치하는 항목이 하나 이상 있는지)만 알면 됩니다. grep -q일단 찾으면 검색을 중지하므로 이것이 더 효율적이기 때문입니다 . grep(표준) 옵션을 지원하지 않는 -q이전 구현 의 경우 첫 번째 일치에서 중지 되지만 파일 이름을 출력하는 fgrep -le "$2" > /dev/null.for 를 사용할 수 있습니다 (여기에서는 출력을 리디렉션하여 삭제합니다 ).-lfgrep/dev/null

답변3

Bash는 기본적으로 이를 지원합니다.

$ string1="abcmoocow"
$ string2="moo"
$ if [[ $string1 == *$string2* ]]; then echo "Match"; else echo "No Match"; fi
Match
$ string1="abccrowcow"
$ if [[ $string1 == *$string2* ]]; then echo "Match"; else echo "No Match"; fi
No Match

또한 귀하의 예를 수정하십시오.

if $(echo $1 | grep -c $2) ; then

이 되다:

if [ -n "$(echo $1 | grep -c $2)" ]; then

(grep이 데이터를 반환하는지 확인)

또한 종료 코드도 사용할 수 있습니다.

$ echo bob | grep "o" &>/dev/null; echo $?
0
$ echo bob | grep "z" &>/dev/null; echo $?
1

관련 정보