grep을 통해 확인하는 데 문제가 있음

grep을 통해 확인하는 데 문제가 있음
list="feature test release"
branch=feature/fix

분기 이름이 목록의 접두사로 시작하지 않는지 확인한 다음 명령을 종료하려고 합니다. 분기에 목록의 접두사 중 하나가 있는 경우 유효합니다.

 echo $list| grep -e "$branch/[a-zA-Z0-9]" ; echo $?

불행히도 이 명령도 작동하지 않습니다. 어떤 아이디어가 있나요? 즉 test/bla, 유효한 분기 이름이지만 testtest/bla그렇지 않습니다.

편집: 을 사용하고 있습니다 sh. 유효한 접두사 목록은 단일 문자열이나 배열일 수 있으며 둘 다 사용할 수 있습니다.

답변1

변수에 유효한 접두사가 필요하지 않은 경우 다음 해결 방법 중 하나를 사용할 수 있습니다.

예를 들어 feature/foo/bar유효한지 여부에 따라 마지막 하나만 삭제하거나 /*모두 삭제해야 합니다.

brancha 가 포함되어 있는지 확인하려면 별도의 테스트가 필요할 수 있습니다 /.

check.sh:

#!/bin/sh

# foo/bar --> ^foo$
# foo --> ^foo$
# foo/bar/baz --> ^foo$
pattern='^'"${branch%%/*}"'$'

# search for pattern in input, suppress output
grep "$pattern" >/dev/null <<EOF
feature
test
release
EOF

echo $?

시험

$ branch=featur/fix ./check.sh
0
$ branch=foo/fix ./check.sh
1
$ branch=xfeature/fix ./check.sh
1
$ branch=featurex/fix ./check.sh
1

편집하다:

에서 언급했듯이스티븐 차제라스branch='.*'' 제공된 분기 이름에 for와 같은 정규식 메타 문자가 포함된 경우 위의 해결 방법은 예기치 않은 일치 항목을 생성할 수 있습니다.

확인하려는 정확한 값에 따라 문자열을 와 같은 구분 문자로 묶어 이를 방지할 수 있습니다 /.

# ...
pattern="/${branch%%/*}/"
# ...
fgrep "$pattern" >/dev/null <<EOF
/feature/
/test/
/release/
EOF
# ...

check2.sh:

#!/bin/sh

# removes longest match /*
# foo/bar/baz --> foo
case "${branch%%/*}" in
feature|test|release)
    echo valid 1
    ;;
*)
    echo invalid 1
    ;;
esac

# removes shortedt match /*
# foo/bar/baz --> foo/bar
case "${branch%/*}" in
feature|test|release)
    echo valid 2
    ;;
*)
    echo invalid 2
    ;;
esac

시험

$ branch=feature/fix ./check2.sh
valid 1
valid 2
$ branch=feature/fix/bla ./check2.sh
valid 1
invalid 2
$ branch=xfeature/fix ./check2.sh
invalid 1
invalid 2
$ branch=featurex/fix ./check2.sh
invalid 1
invalid 2

답변2

스칼라 변수에 공백으로 구분된 단어 목록이 포함되어 있고 그 단어 뒤에 하나 이상의 ASCII 산술이 $list오는지 확인하려는 경우 POSIX에서는 다음을 수행할 수 있습니다.$branch/sh

validate() (export LC_ALL=C
  list=$1 branch=$2
  case $branch in
    (*' '*) return 1;;
  esac
  case ${branch##*/} in
    ("" | *[![:alnum:]]*) return 1;;
  esac
  case " $list " in
    (*" ${branch%/*} "*) return 0;;
    (*) return 1;;
  esac
)

그런 다음:

if validate "$list" "$branch"; then
  echo OK
else
  echo KO
fi

행이 아닌 임의의 문자열에 대해 정규식 일치를 수행하려면 POSIXly에서 기본 옵션은 exprand it's :연산자입니다. 비록 기본 정규식을 사용하고 and it awk's ~연산자(확장 정규식을 사용하는)와 일부 디자인 문제가 있지만 말입니다.

여기서는 다음과 같이 합니다( $list정규식 연산자가 아닌 단어가 있다고 가정).

validate() {
  LC_ALL=C awk -- '
    BEGIN {
      regexp = ARGV[1]
      branch = ARGV[2]
      gsub(" ", "|", regexp)
      regexp = "^("regexp")/[a-zA-Z0-9]+$"
      exit !(branch ~ regexp)
    }' "$@"
}

(여기에서는 POSIX 문자 클래스를 지원하지 않는 구현이 여전히 발생하기 때문에 [a-zA-Z0-9]대신 사용되었습니다 .)[[:alnum:]]awk

기억해야 할 몇 가지 사항은 다음과 같습니다.

  • grep줄 단위로 작동하므로 해당 문자열에 개행 문자가 포함되어 있지 않은지 확인하지 않는 한 임의 문자열의 유효성을 검사하는 데 사용할 수 없습니다.
  • echo $listPOSIX 셸에서는 매개변수 확장을 인용해야 합니다. 그렇지 않으면 분할+glob(no ) 의 영향을 받습니다.
  • echo임의의 데이터를 출력하는데 사용할 수 없으므로 반드시 사용 printf하시기 echo $list바랍니다 printf '%s\n' "$list".
  • 이와 같은 범위는 0-9A-Za-zC 언어 환경에서만 사용할 수 있습니다. C 로케일에서는 [0-9A-Za-z]동일한 콘텐츠와 정확히 일치합니다 [[:alnum:]].

답변3

@Bodo의 한 줄 버전에 대한 평가는 다음과 같습니다.

echo $list | tr ' ' '\n' | grep '^'"${branch%%/*}"'$'; if [[ $? -eq 0 ]]; then echo  "VALID NAME"; else echo "NOPE"; exit 1; fi;

답변4

이렇게 하면,

list="feature test release"
branch=feature/fix
echo $list| grep -e "$branch/[a-zA-Z0-9]"

$IFS(그리고 인용하는 것을 잊었기 때문에 수정되지 않았다고 가정하면 $list) 실제로 다음과 같이 작성하고 있습니다.

echo feature test release | grep -e 'feature/fix/[a-zA-Z0-9]'

feature/fix/X이것은 문자열에서 (모든 영숫자 문자에 대한) 패턴을 찾습니다 . 그건 작동하지 않습니다.Xfeature test release

목록 형식을 정규식으로 변경하고 태그를 정규식과 비교할 수 있습니다.

listRE="^($(printf '%s\n' "$list" | tr ' ' '|'))/"    # ^(feature|test|release)/
printf '%s\n' "$branch" | grep -E "$listRE"; echo "$?"

관련 정보