programing

Bash에서 문자열이 어떤 값으로 시작하는지 확인하려면 어떻게 해야 합니까?

easyjava 2023. 5. 29. 21:54
반응형

Bash에서 문자열이 어떤 값으로 시작하는지 확인하려면 어떻게 해야 합니까?

문자열이 "node"(예: "node001")로 시작하는지 확인하고 싶습니다.비슷한 것

if [ $HOST == user* ]
  then
  echo yes
fi

어떻게 하면 정확하게 할 수 있을까요?


HOST가 "user1"인지 "node"로 시작하는지 확인하기 위해 식을 결합해야 합니다.

if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi

> > > -bash: [: too many arguments

어떻게 하면 정확하게 할 수 있을까요?

Advanced Bash 스크립팅 가이드의 이 토막글은 다음과 같습니다.

# The == comparison operator behaves differently within a double-brackets
# test than within single brackets.

[[ $a == z* ]]   # True if $a starts with a "z" (wildcard matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).

그래서 여러분은 거의 정확하게 답했습니다. 단일 괄호가 아니라 이중 괄호가 필요했습니다.


두 번째 질문과 관련하여 다음과 같이 작성할 수 있습니다.

HOST=user1
if  [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
    echo yes1
fi

HOST=node001
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
    echo yes2
fi

메아리칠 것입니다.

yes1
yes2

바시의if구문은 (IMO)에 익숙해지기 어렵습니다.

Bash(를 , 연산자인 Bash(v3+)를 하는 것을 참조하십시오.=~를 들면 를들면예,

if [[ "$HOST" =~ ^user.* ]]; then
    echo "yes"
fi

일치시키는 것this or that정식에서사를 합니다.|를 들면 를들면예,

if [[ "$HOST" =~ ^user.*|^host1 ]]; then
    echo "yes"
fi

참고 - '적절한' 정규식 구문입니다.

  • user*은 단입니다.use 0 이상 발생하는 0 또그 이의생 상고는.r,그렇게use그리고.userrrr일치합니다.
  • user.*은 단입니다.user 어떤 0 그 을 하기 에 그고어캐의 0 의상발생, 서래그리.user1,userX일치합니다.
  • ^user.*하는 것을 의미합니다.user.*$HOST 시작 부분에서.

정규식 구문에 익숙하지 않은 경우 이 리소스를 참조하십시오.

참고로 배쉬는=~연산자는 오른쪽이 따옴표로 묶이지 않은 경우에만 정규식 일치를 수행합니다.오른쪽을 따옴표로 묶은 경우, "패턴의 모든 부분을 따옴표로 묶어서 문자열과 일치하도록 할 수 있습니다."매개 변수 확장을 수행할 때도 오른쪽을 따옴표로 묶어서는 안 됩니다.

저는 항상 POSIX를 고수하려고 노력합니다.shBash 확장을 사용하는 대신, 스크립팅의 주요 포인트 중 하나는 이식성이기 때문입니다(프로그램을 교체하는 것이 아니라 연결하는 것 외에도).

shis-relay할 수 ."is-relay" ▁there."다있.

case $HOST in node*)
    # Your code here
esac

나이가 많고, 비뚤고, 비열한 것을 감안할 때 (그리고 바시는 치료제가 아닙니다:더 복잡하고 일관성이 떨어지며 휴대성이 떨어집니다.) 기능 측면에서 매우 우수한 점을 지적하고자 합니다. 구문 는 구요다소같음다습과니는문일부▁while다▁like▁elements같▁syntax니습▁some다.case기본 제공되며, 결과 생성물은 다른 작업과 다르지 않습니다.다음과 같은 방법으로 구성할 수 있습니다.

if case $HOST in node*) true;; *) false;; esac; then
    # Your code here
fi

또는 더 짧습니다.

if case $HOST in node*) ;; *) false;; esac; then
    # Your code here
fi

또는 더 짧게(그냥 발표하기 위해)!로서 -- 입니다.) 어소요서로언이다 --하지만은지나스니입타일쁜금것)▁as다니입일스타▁now.

if ! case $HOST in node*) false;; esac; then
    # Your code here
fi

명시적으로 말하는 것을 좋아한다면, 자신만의 언어 요소를 만드세요:

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

사실 이건 꽤 좋지 않나요?

if beginswith node "$HOST"; then
    # Your code here
fi

그리고 그 이후로sh기본적으로 작업 및 문자열 목록(및 작업이 구성된 내부 프로세스)뿐이므로 이제는 가벼운 기능의 프로그래밍도 수행할 수 있습니다.

beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; }

all() {
    test=$1; shift
    for i in "$@"; do
        $test "$i" || return
    done
}

all "beginswith x" x xy xyz ; checkresult  # Prints TRUE
all "beginswith x" x xy abc ; checkresult  # Prints FALSE

우아하네요.내가 옹호하는 것은 아닙니다.sh심각한 모든 것에 대해 -- 그것은 실제 요구 사항에서 너무 빨리 깨집니다(람다가 없으므로, 우리는 끈을 사용해야 합니다).그러나 문자열을 사용하여 함수 호출을 중첩할 수 없으며 파이프를 사용할 수 없습니다.)

문자열에서 확인할 부분만 선택할 수 있습니다.

if [ "${HOST:0:4}" = user ]

후속 질문의 경우 OR을 사용할 수 있습니다.

if [[ "$HOST" == user1 || "$HOST" == node* ]]

나는 이미 게시된 다른 방법을 선호하지만, 어떤 사람들은 다음과 같은 방법을 사용하기를 좋아합니다.

case "$HOST" in 
    user1|node*) 
            echo "yes";;
        *)
            echo "no";;
esac

편집:

위의 사례 진술에 귀하의 대안을 추가했습니다.

편집한 버전에 괄호가 너무 많습니다.다음과 같이 표시되어야 합니다.

if [[ $HOST == user1 || $HOST == node* ]];

제가 여기서 대부분의 답이 꽤 정확하다고 생각하지만, 그 중 많은 것들은 불필요한 바시즘을 포함하고 있습니다.POSIX 매개 변수 확장은 필요한 모든 것을 제공합니다.

[ "${host#user}" != "${host}" ]

그리고.

[ "${host#node}" != "${host}" ]

${var#expr}하는 가장 작은 합니다.expr${var}그리고 그것을 돌려줍니다.그러므로 만약${host}로 시작하지 않음user(node),${host#user}(${host#node}는 )과 .${host}.

expr와일드카드를 허용하므로${host#node??}그리고 친구들도 일을 합니다.

때부터#Bash에 의미가 있어요, 저는 다음과 같은 해결책에 도달했습니다.

또한 공간 등을 극복하기 위해 "로 문자열을 패킹하는 것을 더 좋아합니다.

A="#sdfs"
if [[ "$A" == "#"* ]];then
    echo "Skip comment line"
fi

Mark Rushakoff의 가장 높은 순위 답변에 구문 세부사항을 조금 더 추가합니다.

그 표현은

$HOST == node*

다음과 같이 쓸 수도 있습니다.

$HOST == "node"*

효과는 동일합니다.와일드카드가 따옴표로 묶인 텍스트 밖에 있는지 확인하십시오.와일드카드가 따옴표 안에 있으면 문자 그대로 해석됩니다(즉, 와일드카드가 아닙니다).

@OP, 두 질문 모두 case/esac을 사용할 수 있습니다.

string="node001"
case "$string" in
  node*) echo "found";;
  * ) echo "no node";;
esac

두번째 질문

case "$HOST" in
 node*) echo "ok";;
 user) echo "ok";;
esac

case "$HOST" in
 node*|user) echo "ok";;
esac

또는 Bash 4.0

case "$HOST" in
 user) ;&
 node*) echo "ok";;
esac

단순하게 받아들여라.

word="appel"

if [[ $word = a* ]]
then
  echo "Starts with a"
else
  echo "No match"
fi
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi

것이 작동하지 않기 때문입니다. 왜냐하면 모든 것이기 때문입니다.[,[[,그리고.test동일한 비재귀 문법을 인식합니다.Bashman 페이지의 조건식 섹션을 참조하십시오.

SUSv3는 다음과 같이 말합니다.

KornShell에서 파생된 조건부 명령어([])는 초기 제안에서 셸 명령어 설명에서 제거되었습니다.실제 문제는 테스트 명령([)의 오용이며, 셸에 넣는 것은 문제를 해결하는 잘못된 방법이라는 반론이 제기되었습니다.대신 적절한 설명서와 새 셸 예약 단어(!)로 충분합니다.

여러 테스트 작업이 필요한 테스트는 오류 발생 가능성이 높은 테스트 -o 플래그를 사용하지 않고 테스트 명령 및 셸 논리의 개별 호출을 사용하여 셸 수준에서 수행할 수 있습니다.

이런 식으로 작성해야 하지만 테스트에서 지원하지 않습니다.

if [ $HOST == user1 -o $HOST == node* ];
then
echo yes
fi

test는 문자열 동일성을 위해 =를 사용하며, 더 중요한 것은 패턴 일치를 지원하지 않는다는 입니다.

case/esac패턴 매칭을 잘 지원합니다.

case $HOST in
user1|node*) echo yes ;;
esac

Bash에 의존하지 않고 구문이 이식 가능하다는 추가적인 이점이 있습니다.단일 유닉스 규격에서 명령어:

case word in
    [(]pattern1) compound-list;;
    [[(]pattern[ | pattern] ... ) compound-list;;] ...
    [[(]pattern[ | pattern] ... ) compound-list]
esac

grep

채, 이고, POSIX보다 더 .case솔루션:

mystr="abcd"
if printf '%s' "$mystr" | grep -Eq '^ab'; then
  echo matches
fi

설명:

호출 가능한 함수로 만들기 위해 @markrushakoff의 답변을 수정했습니다.

function yesNo {
  # Prompts user with $1, returns true if response starts with y or Y or is empty string
  read -e -p "
$1 [Y/n] " YN

  [[ "$YN" == y* || "$YN" == Y* || "$YN" == "" ]]
}

다음과 같이 사용합니다.

$ if yesNo "asfd"; then echo "true"; else echo "false"; fi

asfd [Y/n] y
true

$ if yesNo "asfd"; then echo "true"; else echo "false"; fi

asfd [Y/n] Y
true

$ if yesNo "asfd"; then echo "true"; else echo "false"; fi

asfd [Y/n] yes
true

$ if yesNo "asfd"; then echo "true"; else echo "false"; fi

asfd [Y/n]
true

$ if yesNo "asfd"; then echo "true"; else echo "false"; fi

asfd [Y/n] n
false

$ if yesNo "asfd"; then echo "true"; else echo "false"; fi

asfd [Y/n] ddddd
false

지정된 기본값을 제공하는 보다 복잡한 버전은 다음과 같습니다.

function toLowerCase {
  echo "$1" | tr '[:upper:]' '[:lower:]'
}

function yesNo {
  # $1: user prompt
  # $2: default value (assumed to be Y if not specified)
  # Prompts user with $1, using default value of $2, returns true if response starts with y or Y or is empty string

  local DEFAULT=yes
  if [ "$2" ]; then local DEFAULT="$( toLowerCase "$2" )"; fi
  if [[ "$DEFAULT" == y* ]]; then
    local PROMPT="[Y/n]"
  else
    local PROMPT="[y/N]"
  fi
  read -e -p "
$1 $PROMPT " YN

  YN="$( toLowerCase "$YN" )"
  { [ "$YN" == "" ] && [[ "$PROMPT" = *Y* ]]; } || [[ "$YN" = y* ]]
}

다음과 같이 사용합니다.

$ if yesNo "asfd" n; then echo "true"; else echo "false"; fi

asfd [y/N]
false

$ if yesNo "asfd" n; then echo "true"; else echo "false"; fi

asfd [y/N] y
true

$ if yesNo "asfd" y; then echo "true"; else echo "false"; fi

asfd [Y/n] n
false

언급URL : https://stackoverflow.com/questions/2172352/in-bash-how-can-i-check-if-a-string-begins-with-some-value

반응형