etc./StackOverFlow

Bash에서 문자열에 하위 문자열이 포함되어 있는지 확인하는 방법

청렴결백한 만능 재주꾼 2021. 11. 5. 23:09
반응형

질문자 :davidsheldon


Bash에 문자열이 있습니다.

 string="My string"

다른 문자열이 포함되어 있는지 어떻게 테스트할 수 있습니까?

 if [ $string ?? 'foo' ]; then echo "It's there!" fi

어디 ?? 내 알 수 없는 연산자입니다. echogrep 합니까?

 if echo "$string" | grep 'foo'; then echo "It's there!" fi

좀 서투르게 생겼네요.



이중 대괄호를 사용하는 경우 케이스 문 외부에서도 Marcus의 답변(* 와일드카드)을 사용할 수 있습니다.

 string='My long string' if [[ $string == *"My long"* ]]; then echo "It's there!" fi

바늘 문자열의 공백은 큰따옴표 사이에 배치 * 와일드카드는 외부에 있어야 합니다. 또한 정규식 연산자 =~ == )가 사용된다는 점에 유의하십시오.


Adam Bellaire

정규식 접근 방식을 선호하는 경우:

 string='My string'; if [[ $string =~ "My" ]]; then echo "It's there!" fi

Matt Tardiff

if 문을 사용하는지 잘 모르겠지만 case 문으로 비슷한 효과를 얻을 수 있습니다.

 case "$string" in *foo*) # Do stuff ;; esac

Marcus Griep

stringContain 변형(호환성 또는 대소문자 독립적)

이 스택 오버플로 답변은 대부분 Bash 에 대해 이야기하므로 이 게시물 맨 아래에 사례 독립적인 Bash 기능을 게시했습니다...

어쨌든 거기에 내

호환 가능한 답변

Bash 관련 기능을 사용하는 답변이 이미 많기 때문에 BusyBox 와 같이 기능이 좋지 않은 셸에서 작업하는 방법이 있습니다.

 [ -z "${string##*$reqsubstr*}" ]

실제로 이것은 다음을 제공할 수 있습니다.

 string='echo "My string"' for reqsubstr in 'o "M' 'alt' 'str';do if [ -z "${string##*$reqsubstr*}" ] ;then echo "String '$string' contain substring: '$reqsubstr'." else echo "String '$string' don't contain substring: '$reqsubstr'." fi done

이것은 Bash, Dash , KornShell ( ksh ) 및 ash (BusyBox)에서 테스트되었으며 결과는 항상 다음과 같습니다.

 String 'echo "My string"' contain substring: 'o "M'. String 'echo "My string"' don't contain substring: 'alt'. String 'echo "My string"' contain substring: 'str'.

하나의 기능으로

@EeroAaltonen이 요청한 대로 동일한 셸에서 테스트한 동일한 데모 버전이 있습니다.

 myfunc() { reqsubstr="$1" shift string="$@" if [ -z "${string##*$reqsubstr*}" ] ;then echo "String '$string' contain substring: '$reqsubstr'."; else echo "String '$string' don't contain substring: '$reqsubstr'." fi }

그 다음에:

 $ myfunc 'o "M' 'echo "My String"' String 'echo "My String"' contain substring 'o "M'. $ myfunc 'alt' 'echo "My String"' String 'echo "My String"' don't contain substring 'alt'.

주의: 따옴표 및/또는 큰따옴표를 이스케이프하거나 큰따옴표로 묶어야 합니다.

 $ myfunc 'o "M' echo "My String" String 'echo My String' don't contain substring: 'o "M'. $ myfunc 'o "M' echo \"My String\" String 'echo "My String"' contain substring: 'o "M'.

간단한 기능

이것은 BusyBox, Dash 및 Bash에서 테스트되었습니다.

 stringContain() { [ -z "${2##*$1*}" ]; }

그럼 지금:

 $ if stringContain 'o "M3' 'echo "My String"';then echo yes;else echo no;fi no $ if stringContain 'o "M' 'echo "My String"';then echo yes;else echo no;fi yes

... 또는 @Sjlver가 지적한 대로 제출된 문자열이 비어 있을 수 있는 경우 함수는 다음과 같이 됩니다.

 stringContain() { [ -z "${2##*$1*}" ] && [ -z "$1" -o -n "$2" ]; }

또는 Adrian Günter의 의견 에서 제안한 대로 -o 스위치를 피합니다.

 stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ];};}


Community Wiki

쉘 스크립팅은 언어라기보다 명령 모음에 가깝다는 것을 기억해야 합니다. 본능적으로 당신은 이 "언어"가 if [ 또는 [[ . 둘 다 성공 또는 실패를 나타내는 종료 상태를 반환하는 명령일 뿐입니다(다른 모든 명령과 마찬가지로). 그런 이유로 [ 명령이 아닌 grep

그냥 해:

 if grep -q foo <<<"$string"; then echo "It's there" fi

이제 if (세미콜론으로 완료)에 대해 생각하고 있으므로 테스트 중인 문자열의 소스를 재고해 보는 것이 어떻습니까?

 ## Instead of this filetype="$(file -b "$1")" if grep -q "tar archive" <<<"$filetype"; then #... ## Simply do this if file -b "$1" | grep -q "tar archive"; then #...

-q 옵션은 반환 코드만 원하기 때문에 grep이 아무 것도 출력하지 않도록 합니다. <<< 는 쉘이 다음 단어를 확장하고 명령에 대한 입력으로 사용하도록 합니다. << here 문서의 한 줄 버전입니다(표준인지 Bashism인지 확실하지 않음).


Mark Baker

허용되는 답변이 가장 좋지만 이를 수행하는 방법이 여러 가지이므로 다음과 같은 또 다른 솔루션이 있습니다.

 if [ "$string" != "${string/foo/}" ]; then echo "It's there!" fi

${var/search/replace}$var search 의 첫 번째 인스턴스가 replace 로 대체됩니다 $var 변경하지 않음). foo 를 아무 것도 바꾸지 않고 문자열이 변경된 경우 분명히 foo 가 발견되었습니다.


ephemient

따라서 질문에 대한 유용한 솔루션이 많이 있습니다. 그러나 가장 빠른/가장 적은 리소스를 사용하는 것은 무엇입니까?

이 프레임을 사용한 반복 테스트:

 /usr/bin/time bash -c 'a=two;b=onetwothree; x=100000; while [ $x -gt 0 ]; do TEST ; x=$(($x-1)); done'

매번 TEST 교체:

 [[ $b =~ $a ]] 2.92 user 0.06 system 0:02.99 elapsed 99% CPU [ "${b/$a//}" = "$b" ] 3.16 user 0.07 system 0:03.25 elapsed 99% CPU [[ $b == *$a* ]] 1.85 user 0.04 system 0:01.90 elapsed 99% CPU case $b in *$a):;;esac 1.80 user 0.02 system 0:01.83 elapsed 99% CPU doContain $a $b 4.27 user 0.11 system 0:04.41 elapsed 99%CPU

(doContain은 F. Houri의 답변에 있었습니다)

그리고 킥킥거리기 위해:

 echo $b|grep -q $a 12.68 user 30.86 system 3:42.40 elapsed 19% CPU !ouch!

따라서 단순 대체 옵션은 확장 테스트에서든 케이스에서든 예측 가능하게 승리합니다. 케이스는 휴대용입니다.

100000 greps까지 파이핑하는 것은 예상대로 고통스럽습니다! 필요 없이 외부 유틸리티를 사용하는 것에 대한 오래된 규칙은 사실입니다.


Paul Hedderly

이것은 또한 작동합니다:

 if printf -- '%s' "$haystack" | egrep -q -- "$needle" then printf "Found needle in haystack" fi

그리고 음성 테스트는 다음과 같습니다.

 if ! printf -- '%s' "$haystack" | egrep -q -- "$needle" then echo "Did not find needle in haystack" fi

나는 이 스타일이 좀 더 고전적이라고 생각합니다. Bash 셸의 기능에 덜 의존적입니다.

-- --abc 또는 -a 와 같은 옵션과 유사한 입력 문자열로부터 보호하는 데 사용되는 순수한 POSIX 편집증입니다.

참고: 긴밀한 루프에서 이 코드는 내부 Bash 셸 기능을 사용하는 것보다 훨씬 느릴 것입니다. 하나 또는 두 개의 개별 프로세스가 생성되고 파이프를 통해 연결되기 때문입니다.


kevinarpe

Bash 4+ 예제. 참고: 따옴표를 사용하지 않으면 단어에 공백 등이 포함될 때 문제가 발생합니다. 항상 Bash, IMO에서 인용하십시오.

다음은 Bash 4+의 몇 가지 예입니다.

예 1, 문자열에서 '예'를 확인합니다(대소문자 구분 안 함).

 if [[ "${str,,}" == *"yes"* ]] ;then

예 2, 문자열에서 '예' 확인(대소문자 구분 안 함):

 if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then

예 3, 문자열에서 '예' 확인(대소문자 구분):

 if [[ "${str}" == *"yes"* ]] ;then

예 4, 문자열에서 '예' 확인(대소문자 구분):

 if [[ "${str}" =~ "yes" ]] ;then

예 5, 정확히 일치(대소문자 구분):

 if [[ "${str}" == "yes" ]] ;then

예 6, 정확히 일치(대소문자 구분 안 함):

 if [[ "${str,,}" == "yes" ]] ;then

예 7, 정확히 일치:

 if [ "$a" = "$b" ] ;then

예 8, 와일드카드 일치 .ext(대소문자 구분 안 함):

 if echo "$a" | egrep -iq "\.(mp[3-4]|txt|css|jpg|png)" ; then

즐기다.


Mike Q

Paul 은 성능 비교에서 다음과 같이 언급했습니다.

 if echo "abcdefg" | grep -q "bcdef"; then echo "String contains is true." else echo "String contains is not true." fi

이것은 Marcus가 제공한 답변 의 'case "$string"'과 같이 POSIX를 준수하지만 case 문 답변보다 읽기가 약간 더 쉽습니다. 또한 이것은 case 문을 사용하는 것보다 훨씬 느립니다. Paul이 지적했듯이 루프에서 사용하지 마십시오.


Samuel

이것은 어떤가요:

 text=" <tag>bmnmn</tag> " if [[ "$text" =~ "<tag>" ]]; then echo "matched" else echo "not matched" fi

Stefan

이 스택 오버플로 답변 은 공백 및 대시 문자를 트래핑하는 유일한 답변이었습니다.

 # For null cmd arguments checking to_check=' -t' space_n_dash_chars=' -' [[ $to_check == *"$space_n_dash_chars"* ]] && echo found

Yordan Georgiev

[[ $string == *foo* ]] && echo "It's there" || echo "Couldn't find"

Jahid

하나는:

 [ $(expr $mystring : ".*${search}.*") -ne 0 ] && echo 'yes' || echo 'no'

chemila

.bash_profile 파일 및 grep 사용 방법:

PATH 환경 변수에 두 개의 bin 디렉토리가 포함되어 있으면 추가하지 마십시오.

 # .bash_profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi U=~/.local.bin:~/bin if ! echo "$PATH" | grep -q "home"; then export PATH=$PATH:${U} fi

Leslie Satenstein

여기에 답변된 질문의 확장 문자열에 POSIX sh에 다른 문자열이 포함되어 있는지 어떻게 알 수 있습니까? :

이 솔루션은 특수 문자와 함께 작동합니다.

 # contains(string, substring) # # Returns 0 if the specified string contains the specified substring, # otherwise returns 1. contains() { string="$1" substring="$2" if echo "$string" | $(type -p ggrep grep | head -1) -F -- "$substring" >/dev/null; then return 0 # $substring is in $string else return 1 # $substring is not in $string fi } contains "abcd" "e" || echo "abcd does not contain e" contains "abcd" "ab" && echo "abcd contains ab" contains "abcd" "bc" && echo "abcd contains bc" contains "abcd" "cd" && echo "abcd contains cd" contains "abcd" "abcd" && echo "abcd contains abcd" contains "" "" && echo "empty string contains empty string" contains "a" "" && echo "a contains empty string" contains "" "a" || echo "empty string does not contain a" contains "abcd efgh" "cd ef" && echo "abcd efgh contains cd ef" contains "abcd efgh" " " && echo "abcd efgh contains a space" contains "abcd [efg] hij" "[efg]" && echo "abcd [efg] hij contains [efg]" contains "abcd [efg] hij" "[effg]" || echo "abcd [efg] hij does not contain [effg]" contains "abcd *efg* hij" "*efg*" && echo "abcd *efg* hij contains *efg*" contains "abcd *efg* hij" "d *efg* h" && echo "abcd *efg* hij contains d *efg* h" contains "abcd *efg* hij" "*effg*" || echo "abcd *efg* hij does not contain *effg*"

Alex Skrypnyk

POSIX /BusyBox 질문은 정답(IMHO)을 제공하지 않고 닫혀 있으므로 여기에 답변을 게시합니다.

가능한 가장 짧은 대답은 다음과 같습니다.

 [ ${_string_##*$_substring_*} ] || echo Substring found!

또는

 [ "${_string_##*$_substring_*}" ] || echo 'Substring found!'

이중 해시 는 일부 쉘( ash )에서 필수입니다. 위는 하위 문자열을 찾을 수 없을 때 [ stringvalue ] 그것은 오류를 반환하지 않습니다. 부분 문자열이 발견되면 결과는 비어 있고 [ ] 평가합니다. 문자열이 완전히 대체되었기 때문에 오류 코드 1이 발생합니다( * 로 인해).

가장 짧은 일반적인 구문:

 [ -z "${_string_##*$_substring_*}" ] && echo 'Substring found!'

또는

 [ -n "${_string_##*$_substring_*}" ] || echo 'Substring found!'

다른 것:

 [ "${_string_##$_substring_}" != "$_string_" ] && echo 'Substring found!'

또는

 [ "${_string_##$_substring_}" = "$_string_" ] || echo 'Substring found!'

단일 등호를 주목하십시오!


FifthAxiom

grep -q 는 이 목적에 유용합니다.

awk 사용하는 것과 동일합니다.

 string="unix-bash 2389" character="@" printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

산출:

찾을 수 없음

 string="unix-bash 2389" character="-" printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

산출:

설립하다

원본 출처: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html


Jadu Saikia

나는 세드를 좋아한다.

 substr="foo" nonsub="$(echo "$string" | sed "s/$substr//")" hassub=0 ; [ "$string" != "$nonsub" ] && hassub=1

편집, 논리:

  • sed를 사용하여 문자열에서 부분 문자열의 인스턴스 제거

  • 새 문자열이 이전 문자열과 다른 경우 하위 문자열이 존재합니다.


ride

나는 이 기능이 꽤 자주 필요하다는 것을 알았으므로 .bashrc 이와 같이 집에서 만든 셸 기능을 사용하여 필요할 때마다 기억하기 쉬운 이름으로 재사용할 수 있습니다.

 function stringinstring() { case "$2" in *"$1"*) return 0 ;; esac return 1 }

$string1 (예: abc )이 $string2 (예: 123abcABC )에 포함되어 있는지 테스트하려면 stringinstring "$string1" "$string2" 를 실행하고 반환 값을 확인하기만 하면 됩니다. 예를 들면

 stringinstring "$str1" "$str2" && echo YES || echo NO

Kurt Pfeifle

정확한 단어 일치:

 string='My long string' exactSearch='long' if grep -E -q "\b${exactSearch}\b" <<<${string} >/dev/null 2>&1 then echo "It's there" fi

Eduardo Cuomo

oobash를 시도하십시오.

Bash 4용 OO 스타일 문자열 라이브러리입니다. 독일어 움라우트를 지원합니다. Bash로 작성되었습니다.

많은 기능을 사용할 수 있습니다 -base64Decode , -base64Encode , -capitalize , -center , -charAt , -concat , -contains , -count , -endsWith , -equals , -equalsIgnoreCase , -reverse , -hashCode , -indexOf , -isAlnum , -isAlpha , -isAscii , -isDigit , -isEmpty , -isHexDigit , -isLowerCase , -isSpace , -isPrintable , -isUpperCase , -isVisible , -lastIndexOf , -length , -matches , -replaceAll , -replaceFirst , -startsWith , -substring , -swapCase , -toLowerCase , -toString , -toUpperCase , -trim-zfill .

포함 예를 살펴보십시오.

 [Desktop]$ String a testXccc [Desktop]$ a.contains tX true [Desktop]$ a.contains XtX false

oobash는 Sourceforge.net에서 사용할 수 있습니다 .


andreas

일반 바늘 건초 더미의 예는 변수를 다음입니다

 #!/bin/bash needle="a_needle" haystack="a_needle another_needle a_third_needle" if [[ $haystack == *"$needle"* ]]; then echo "needle found" else echo "needle NOT found" fi

Pipo

case $string in (*foo*) # Do stuff esac

이것은 https://stackoverflow.com/a/229585/11267590 과 동일한 답변입니다. 그러나 단순한 스타일과 POSIX 호환.


Koichi Nakashima

이 기능을 사용합니다(하나의 종속성은 포함되어 있지 않지만 명백한). 아래 표시된 테스트를 통과합니다. 함수가 0보다 큰 값을 반환하면 문자열이 발견된 것입니다. 대신 1 또는 0을 쉽게 반환할 수 있습니다.

 function str_instr { # Return position of ```str``` within ```string```. # >>> str_instr "str" "string" # str: String to search for. # string: String to search. typeset str string x # Behavior here is not the same in bash vs ksh unless we escape special characters. str="$(str_escape_special_characters "${1}")" string="${2}" x="${string%%$str*}" if [[ "${x}" != "${string}" ]]; then echo "${#x} + 1" | bc -l else echo 0 fi } function test_str_instr { str_instr "(" "'foo@host (dev,web)'" | assert_eq 11 str_instr ")" "'foo@host (dev,web)'" | assert_eq 19 str_instr "[" "'foo@host [dev,web]'" | assert_eq 11 str_instr "]" "'foo@host [dev,web]'" | assert_eq 19 str_instr "a" "abc" | assert_eq 1 str_instr "z" "abc" | assert_eq 0 str_instr "Eggs" "Green Eggs And Ham" | assert_eq 7 str_instr "a" "" | assert_eq 0 str_instr "" "" | assert_eq 0 str_instr " " "Green Eggs" | assert_eq 6 str_instr " " " Green " | assert_eq 1 }

Ethan Post

msg="message" function check { echo $msg | egrep [abc] 1> /dev/null if [ $? -ne 1 ]; then echo "found" else echo "not found" fi } check

이것은 또는 b 또는 c의 모든 발생을 찾을 것입니다


BobMonk

출처 : http:www.stackoverflow.com/questions/229551/how-to-check-if-a-string-contains-a-substring-in-bash

반응형