Ik heb een string in Bash:
string="My string"
Hoe kan ik testen of het een andere tekenreeks bevat?
if [ $string ?? 'foo' ]; then
echo "It's there!"
fi
Waar ??
is mijn onbekende operator. Gebruik ik echo
en grep
?
if echo "$string" | grep 'foo'; then
echo "It's there!"
fi
Dat ziet er een beetje onhandig uit.
Antwoord 1, autoriteit 100%
Je kunt Marcus’s antwoord (*jokertekens)ook buiten een case-statement gebruiken als je dubbele haakjes gebruikt:
string='My long string'
if [[ $string == *"My long"* ]]; then
echo "It's there!"
fi
Houd er rekening mee dat spaties in de naaldtekenreeks tussen dubbele aanhalingstekens moeten worden geplaatst en dat de jokertekens *
erbuiten moeten staan. Merk ook op dat er een eenvoudige vergelijkingsoperator wordt gebruikt (d.w.z. ==
), niet de regex-operator =~
.
Antwoord 2, autoriteit 18%
Als u de voorkeur geeft aan de regex-aanpak:
string='My string';
if [[ $string =~ "My" ]]; then
echo "It's there!"
fi
Antwoord 3, autoriteit 10%
Ik weet niet zeker of ik een if-statement moet gebruiken, maar je kunt een soortgelijk effect krijgen met een case-statement:
case "$string" in
*foo*)
# Do stuff
;;
esac
Antwoord 4, autoriteit 7%
stringContain
varianten (compatible of case zelfstandig)
Omdat deze stack overflow antwoorden vooral over Bash vertellen, ik heb gepost case onafhankelijke Bash functie op de bodem van dit bericht …
Hoe dan ook, daar is mijn
Compatible antwoord
Omdat er al veel antwoorden met behulp van Bash-specifieke kenmerken, is er een manier werkt onder armere-featured schelpen, zoals BusyBox :
[ -z "${string##*$reqsubstr*}" ]
In de praktijk zou dit kunnen geven:
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
Dit werd getest onder Bash, Dash kornshell (ksh
) en ash (BusyBox), en het resultaat is altijd:
String 'echo "My string"' contain substring: 'o "M'.
String 'echo "My string"' don't contain substring: 'alt'.
String 'echo "My string"' contain substring: 'str'.
In één functie
Zoals gesteld door @EeroAaltonen hier is een versie van dezelfde demo, getest onder dezelfde schalen:
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
}
Dan:
$ 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'.
Opmerking:u moet aanhalingstekens escapen of dubbel omsluiten en/of dubbele aanhalingstekens:
$ 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'.
Eenvoudige functie
Dit is getest onder BusyBox, Dash en natuurlijk Bash:
stringContain() { [ -z "${2##*$1*}" ]; }
Dan nu:
$ 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
… Of als de ingediende string leeg zou kunnen zijn, zoals aangegeven door @Sjlver, zou de functie worden:
stringContain() { [ -z "${2##*$1*}" ] && [ -z "$1" -o -n "$2" ]; }
of zoals gesuggereerd door Adrian Günter’s opmerking, waarbij -o
-switches worden vermeden:
stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ];};}
s>
s>
Finale (eenvoudige) functie:
en het omkeren van de tests om ze potentieel sneller te maken:
stringContain() { [ -z "$1" ] || { [ -z "${2##*$1*}" ] && [ -n "$2" ];};}
Met lege snaren:
$ if stringContain '' ''; then echo yes; else echo no; fi
yes
$ if stringContain 'o "M' ''; then echo yes; else echo no; fi
no
Case onafhankelijk (alleen bash!)
Om snaren zonder verzorging te testen, converteert u eenvoudig elke reeks naar kleine letters:
stringContain() {
local _lc=${2,,}
[ -z "$1" ] || { [ -z "${_lc##*${1,,}*}" ] && [ -n "$2" ] ;} ;}
Controleer:
stringContain 'o "M3' 'echo "my string"' && echo yes || echo no
no
stringContain 'o "My' 'echo "my string"' && echo yes || echo no
yes
if stringContain '' ''; then echo yes; else echo no; fi
yes
if stringContain 'o "M' ''; then echo yes; else echo no; fi
no
5, Autoriteit 4%
Denk eraan dat shell-scripting minder is van een taal en meer van een verzameling commando’s. Instinctief denkt u dat deze “taal” vereist dat u een if
met een [
of een [[
[. Beide zijn gewoon opdrachten die een exit-status retourneren die het succes of falen aangeeft (net als elke andere opdracht). Om die reden zou ik grep
gebruiken en niet de opdracht [
.
Doe gewoon:
if grep -q foo <<<"$string"; then
echo "It's there"
fi
Nu je denkt aan if
als het testen van de exit-status van het commando dat erop volgt (compleet met puntkomma), waarom heroverweeg je dan niet de bron van de string die je aan het testen bent?
p>
## 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
#...
De optie -q
zorgt ervoor dat grep niets uitvoert, omdat we alleen de retourcode willen. <<<
zorgt ervoor dat de shell het volgende woord uitbreidt en gebruikt als invoer voor de opdracht, een éénregelige versie van het <<
hier document (Ik weet niet zeker of dit standaard is of een bashisme).
Antwoord 6, autoriteit 2%
Het geaccepteerde antwoord is het beste, maar aangezien er meer dan één manier is om het te doen, is hier een andere oplossing:
if [ "$string" != "${string/foo/}" ]; then
echo "It's there!"
fi
${var/search/replace}
is $var
met de eerste instantie van search
vervangen door replace
, als het wordt gevonden (het verandert $var
niet). Als je foo
door niets probeert te vervangen, en de string is veranderd, dan is duidelijk foo
gevonden.
Antwoord 7, autoriteit 2%
Er zijn dus veel nuttige oplossingen voor de vraag – maar welke is het snelst / gebruikt de minste middelen?
Herhaalde tests met dit frame:
/usr/bin/time bash -c 'a=two;b=onetwothree; x=100000; while [ $x -gt 0 ]; do TEST ; x=$(($x-1)); done'
TEST elke keer vervangen:
[[ $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 zat in het antwoord van F. Houri)
En om te giechelen:
echo $b|grep -q $a 12.68 user 30.86 system 3:42.40 elapsed 19% CPU !ouch!
Dus de eenvoudige vervangingsoptie wint voorspelbaar, of het nu gaat om een uitgebreide test of een zaak. De case is draagbaar.
Pijpen tot 100000 greps is voorspelbaar pijnlijk! De oude regel over het gebruik van externe hulpprogramma’s zonder noodzaak geldt.
Antwoord 8
Dit werkt ook:
if printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
printf "Found needle in haystack"
fi
En de negatieve test is:
if ! printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
echo "Did not find needle in haystack"
fi
Ik veronderstel dat deze stijl wat klassieker is — minder afhankelijk van de kenmerken van de Bash-shell.
Het argument --
is pure POSIX-paranoia, gebruikt om te beschermen tegen invoerreeksen die vergelijkbaar zijn met opties, zoals --abc
of -a
.
OPMERKING: In een strakke lus is deze code veel langzamer dan het gebruik van interne bash shell-functies, omdat één (of twee) afzonderlijke processen via leidingen worden gemaakt en verbonden via leidingen.
9
Bash 4+ voorbeelden. OPMERKING: Niet gebruiken van offertes zal problemen veroorzaken wanneer woorden spaties bevatten, enz. Wezen altijd in Bash, IMO.
Hier zijn enkele voorbeelden bash 4 +:
Voorbeeld 1, cheque ‘ja’ in string (niet hoofdlettergevoelig):
if [[ "${str,,}" == *"yes"* ]] ;then
Voorbeeld 2, controleer op ‘ja’ in string (case ongevoelig):
if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then
Voorbeeld 3, controleer op ‘ja’ in string (hoofdlettergevoelig):
if [[ "${str}" == *"yes"* ]] ;then
Voorbeeld 4, controleer op ‘ja’ in string (hoofdlettergevoelig):
if [[ "${str}" =~ "yes" ]] ;then
Voorbeeld 5, exacte overeenkomst (hoofdlettergevoelig):
if [[ "${str}" == "yes" ]] ;then
Voorbeeld 6, exacte overeenkomst (case ongevoelig):
if [[ "${str,,}" == "yes" ]] ;then
Voorbeeld 7, exacte overeenkomst:
if [ "$a" = "$b" ] ;then
Voorbeeld 8, wildcard match .Ext (case ongevoelig):
if echo "$a" | egrep -iq "\.(mp[3-4]|txt|css|jpg|png)" ; then
Geniet.
10
Zoals Paul vermeldde in zijn prestatievergelijking:
if echo "abcdefg" | grep -q "bcdef"; then
echo "String contains is true."
else
echo "String contains is not true."
fi
Dit is POSIX-compatibel, zoals de ‘case “$string” in’ het antwoord van Marcus, maar het is iets gemakkelijker te lezen dan het antwoord op de case-statement. Houd er ook rekening mee dat dit veel langzamer gaat dan het gebruik van een case-statement. Zoals Paul al zei, gebruik het niet in een lus.
Antwoord 11
Wat dacht je hiervan:
text=" <tag>bmnmn</tag> "
if [[ "$text" =~ "<tag>" ]]; then
echo "matched"
else
echo "not matched"
fi
Antwoord 12
Dit Stack Overflow-antwoordwas de enige die spatie- en streepjestekens opving:
# For null cmd arguments checking
to_check=' -t'
space_n_dash_chars=' -'
[[ $to_check == *"$space_n_dash_chars"* ]] && echo found
Antwoord 13
[[ $string == *foo* ]] && echo "It's there" || echo "Couldn't find"
Antwoord 14
Een daarvan is:
[ $(expr $mystring : ".*${search}.*") -ne 0 ] && echo 'yes' || echo 'no'
Antwoord 15
Mijn .bash_profile-bestand en hoe ik grep heb gebruikt:
Als de omgevingsvariabele PATH mijn twee bin
-mappen bevat, voeg ze dan niet toe,
# .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
Antwoord 16
grep -q
is hiervoor handig.
Hetzelfde met awk
:
string="unix-bash 2389"
character="@"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'
Uitvoer:
Niet gevonden
string="unix-bash 2389"
character="-"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'
Uitvoer:
Gevonden
Originele bron: http:// onstabiele.blogspot.com/2008/06/bash-search-letter-in-string-awk.html
Antwoord 17
Ik hou van sed.
substr="foo"
nonsub="$(echo "$string" | sed "s/$substr//")"
hassub=0 ; [ "$string" != "$nonsub" ] && hassub=1
Bewerken, logica:
-
Gebruik sed om instantie van substring uit string te verwijderen
-
Als de nieuwe tekenreeks verschilt van de oude tekenreeks, bestaat er een subtekenreeks
Antwoord 18
Ik merkte dat ik deze functionaliteit vrij vaak nodig had, dus ik gebruik een zelfgemaakte shell-functie in mijn .bashrc
zoals deze, waardoor ik deze zo vaak kan hergebruiken als nodig is, met een gemakkelijk te onthouden naam:
function stringinstring()
{
case "$2" in
*"$1"*)
return 0
;;
esac
return 1
}
Om te testen of $string1
(zeg, abc) is opgenomen in $string2
(zeg, 123abcABC) Ik hoef alleen maar stringinstring "$string1" "$string2"
uit te voeren en te controleren op de geretourneerde waarde, bijvoorbeeld
stringinstring "$str1" "$str2" && echo YES || echo NO
Antwoord 19
Uitbreiding van de vraag die hier wordt beantwoord Hoe weet je of een string een andere string bevat in POSIX sh?:
Deze oplossing werkt met speciale tekens:
# 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*"
20
Exacte woordwedstrijd:
string='My long string'
exactSearch='long'
if grep -E -q "\b${exactSearch}\b" <<<${string} >/dev/null 2>&1
then
echo "It's there"
fi
21
Probeer Oobash.
Het is een OO-stijl string-bibliotheek voor bash 4. Het heeft ondersteuning voor Duitse Umlauts. Het is geschreven in bash.
Veel functies zijn beschikbaar: -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
, en -zfill
.
Bekijk de Bevat Voorbeeld:
[Desktop]$ String a testXccc
[Desktop]$ a.contains tX
true
[Desktop]$ a.contains XtX
false
oobash is beschikbaar bij SourceForge.net .
22
case $string in (*foo*)
# Do stuff
esac
Dit is hetzelfde antwoord als https://stackoverflow.com/a/229585/11267590. Maar eenvoudige stijl en ook POSIX-compatibel.
Antwoord 23
Ik gebruik deze functie (één afhankelijkheid niet inbegrepen, maar duidelijk). Het doorstaat de onderstaande tests. Als de functie een waarde retourneert > 0 dan is de string gevonden. U kunt in plaats daarvan net zo gemakkelijk 1 of 0 retourneren.
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
}
Antwoord 24
msg="message"
function check {
echo $msg | egrep [abc] 1> /dev/null
if [ $? -ne 1 ];
then
echo "found"
else
echo "not found"
fi
}
check
Hiermee vindt u elk voorkomen van a of b of c