Write a function that checks if a string starts with or contains somethingHow to pass a string parameter on bash function?Function that calls another function with list of arguments doesn't workHow do i create a function to test if the input contains any character?A basic function that doesn't workVIM: function that checks if external program is runningTerminal emulator crashes with function with nested case statements?Test if a string contains a substringCall function that call ffmpeg in loopShell: Using function with parameters in ifDetermining if the first string starts with second string
Why can my keyboard only digest 6 keypresses at a time?
How to learn Linux system internals
Russian word for a male zebra
Can I utilise a baking stone to make crepes?
Write a function that checks if a string starts with or contains something
Why was this person allowed to become Grand Maester?
Are inverted question and exclamation mark supposed to be symmetrical to the "normal" counter-parts?
Advantages of the Exponential Family: why should we study it and use it?
Can a human be transformed into a Mind Flayer?
Why did Intel abandon unified CPU cache?
What are some really overused phrases in French that are common nowadays?
Is it possible to have 2 different but equal size real number sets that have the same mean and standard deviation?
Why are MBA programs closing in the United States?
A word that means "blending into a community too much"
Separate SPI data
How to safely destroy (a large quantity of) valid checks?
Generate basis elements of the Steenrod algebra
How can I remove material from this wood beam?
Who won a Game of Bar Dice?
Is it possible to fly backward if you have really strong headwind?
Solve Riddle With Algebra
Can all groups be thought of as the symmetries of a geometrical object?
Is it possible for a vehicle to be manufactured without a catalytic converter?
If I leave the US through an airport, do I have to return through the same airport?
Write a function that checks if a string starts with or contains something
How to pass a string parameter on bash function?Function that calls another function with list of arguments doesn't workHow do i create a function to test if the input contains any character?A basic function that doesn't workVIM: function that checks if external program is runningTerminal emulator crashes with function with nested case statements?Test if a string contains a substringCall function that call ffmpeg in loopShell: Using function with parameters in ifDetermining if the first string starts with second string
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I want to write a function that checks if a given variable, say, var
, starts with any of the words in a given list of strings. This list won't change.
To instantiate, let's pretend that I want to check if var
starts with aa
, abc
or 3@3
.
Moreover, I want to check if var
contains the character >
.
Let's say this function is called check_func
. My intended usage looks something like
if check_func "$var"; then
do stuff
fi
For example, it should "do stuff" foraardvark
, abcdef
, 3@3com.com
and 12>5
.
I've seen this SO question where a user provides part of the work:
beginswith() case $2 in "$1"*) true;; *) false;; esac;
My idea is that I would iterate over the list mentioned above and use this function. My difficulty lies in not understanding exactly how exiting (or whatever replaces returning) should be done to make this work.
shell string function pattern-matching
New contributor
add a comment |
I want to write a function that checks if a given variable, say, var
, starts with any of the words in a given list of strings. This list won't change.
To instantiate, let's pretend that I want to check if var
starts with aa
, abc
or 3@3
.
Moreover, I want to check if var
contains the character >
.
Let's say this function is called check_func
. My intended usage looks something like
if check_func "$var"; then
do stuff
fi
For example, it should "do stuff" foraardvark
, abcdef
, 3@3com.com
and 12>5
.
I've seen this SO question where a user provides part of the work:
beginswith() case $2 in "$1"*) true;; *) false;; esac;
My idea is that I would iterate over the list mentioned above and use this function. My difficulty lies in not understanding exactly how exiting (or whatever replaces returning) should be done to make this work.
shell string function pattern-matching
New contributor
It just occurred to me that your question is ambiguous. Do you mean (1) I want to check ifvar
starts withaa
. I want to check ifvar
starts withabc
. I want to check ifvar
starts with3@3
. And I want to check ifvar
contains>
. ? Or do you mean (2) I want to check ifvar
starts withaa
,abc
or3@3
, and it also contains>
. ?
– G-Man
7 hours ago
@G-Man The first one. Thanks for bringing that up.
– No Imaginatition
6 hours ago
add a comment |
I want to write a function that checks if a given variable, say, var
, starts with any of the words in a given list of strings. This list won't change.
To instantiate, let's pretend that I want to check if var
starts with aa
, abc
or 3@3
.
Moreover, I want to check if var
contains the character >
.
Let's say this function is called check_func
. My intended usage looks something like
if check_func "$var"; then
do stuff
fi
For example, it should "do stuff" foraardvark
, abcdef
, 3@3com.com
and 12>5
.
I've seen this SO question where a user provides part of the work:
beginswith() case $2 in "$1"*) true;; *) false;; esac;
My idea is that I would iterate over the list mentioned above and use this function. My difficulty lies in not understanding exactly how exiting (or whatever replaces returning) should be done to make this work.
shell string function pattern-matching
New contributor
I want to write a function that checks if a given variable, say, var
, starts with any of the words in a given list of strings. This list won't change.
To instantiate, let's pretend that I want to check if var
starts with aa
, abc
or 3@3
.
Moreover, I want to check if var
contains the character >
.
Let's say this function is called check_func
. My intended usage looks something like
if check_func "$var"; then
do stuff
fi
For example, it should "do stuff" foraardvark
, abcdef
, 3@3com.com
and 12>5
.
I've seen this SO question where a user provides part of the work:
beginswith() case $2 in "$1"*) true;; *) false;; esac;
My idea is that I would iterate over the list mentioned above and use this function. My difficulty lies in not understanding exactly how exiting (or whatever replaces returning) should be done to make this work.
shell string function pattern-matching
shell string function pattern-matching
New contributor
New contributor
edited 30 mins ago
G-Man
14.6k94175
14.6k94175
New contributor
asked 9 hours ago
No ImaginatitionNo Imaginatition
83
83
New contributor
New contributor
It just occurred to me that your question is ambiguous. Do you mean (1) I want to check ifvar
starts withaa
. I want to check ifvar
starts withabc
. I want to check ifvar
starts with3@3
. And I want to check ifvar
contains>
. ? Or do you mean (2) I want to check ifvar
starts withaa
,abc
or3@3
, and it also contains>
. ?
– G-Man
7 hours ago
@G-Man The first one. Thanks for bringing that up.
– No Imaginatition
6 hours ago
add a comment |
It just occurred to me that your question is ambiguous. Do you mean (1) I want to check ifvar
starts withaa
. I want to check ifvar
starts withabc
. I want to check ifvar
starts with3@3
. And I want to check ifvar
contains>
. ? Or do you mean (2) I want to check ifvar
starts withaa
,abc
or3@3
, and it also contains>
. ?
– G-Man
7 hours ago
@G-Man The first one. Thanks for bringing that up.
– No Imaginatition
6 hours ago
It just occurred to me that your question is ambiguous. Do you mean (1) I want to check if
var
starts with aa
. I want to check if var
starts with abc
. I want to check if var
starts with 3@3
. And I want to check if var
contains >
. ? Or do you mean (2) I want to check if var
starts with aa
, abc
or 3@3
, and it also contains >
. ?– G-Man
7 hours ago
It just occurred to me that your question is ambiguous. Do you mean (1) I want to check if
var
starts with aa
. I want to check if var
starts with abc
. I want to check if var
starts with 3@3
. And I want to check if var
contains >
. ? Or do you mean (2) I want to check if var
starts with aa
, abc
or 3@3
, and it also contains >
. ?– G-Man
7 hours ago
@G-Man The first one. Thanks for bringing that up.
– No Imaginatition
6 hours ago
@G-Man The first one. Thanks for bringing that up.
– No Imaginatition
6 hours ago
add a comment |
5 Answers
5
active
oldest
votes
check_prefixes ()
value=$1
for prefix in aa abc 3@3; do
case $value in
"$prefix"*) return 0
esac
done
return 1
check_contains_gt ()
value=$1
case $value in
*">"*) return 0
esac
return 1
var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
printf '"%s" contains ">" and starts with one of the prefixesn' "$var"
fi
I divided the tests up into two functions. Both use case ... esac
and returns success (zero) as soon as this can be determined. If nothing matches, failure (1) is returned.
To make the list of prefixes more of a dynamic list, one could possibly write the first function as
check_prefixes ()
value=$1
shift
for prefix do
case $value in
"$prefix"*) return 0
esac
done
return 1
(the value to inspect is the first argument, which we save in value
and then shift
off the list of arguments to the function; we then iterate over the remaining arguments) and then call it as
check_prefixes "$var" aa abc 3@3
The second function could be changed in a similar manner, into
check_contains ()
value=$1
shift
case $value in
*"$1"*) return 0
esac
return 1
(to check for some arbitrary substring), or
check_contains_oneof ()
value=$1
shift
for substring do
case $value in
*"$substring"*) return 0
esac
done
return 1
(to check for any of a number of substrings)
Thanks. My intended logic is with a logical or instead of a logical and. Should it bevalue
instead ofvar
in the first function's definition?
– No Imaginatition
5 hours ago
@NoImaginatition OK, just change the logic in the code calling the functions (||
instead of&&
). Yes, that's a typo in my code, I'll fix it at once, thanks.
– Kusalananda♦
5 hours ago
I'm trying to combine both functions into one by definingcheck_func()
, but it won't work forecho a >file
. Any idea why?
– No Imaginatition
5 hours ago
@NoImaginatition Always double quote variable expansions ("$1"
) unless you know exactly in what contexts this is not needed.
– Kusalananda♦
5 hours ago
Great, it worked. If it's not much to ask, what is it that it makes it fail without the double quotes? I tried to test if it would expand the second call of$1
, and it seems to expand. I tested it withtest () echo $1 $1;
and it worked fine.
– No Imaginatition
5 hours ago
add a comment |
For bash:
Using the properties of regex you can write start
with ^
and contain
by nothing.
The list of regexes to check start with aa
abc
or 3@3
and contains >
is:
^aa ^abc ^3@3 >
Make that a properly quoted list and ask bash to use regexes (=~
):
check_func()
matched=1
for test_regex in '^aa' '^abc' '^3@3' '>'; do
if [[ $var =~ $test_regex ]] ; then
matched=0
break
fi
done
return "$matched"
var='aaIsAMatch'
if check_func; then
echo "A match was found"
fi
The function has hard-coded the list of matches and the name of the var.
Giving the list of regex in an array variable and the value to test on the first argument:
check_func()
local matched; matched=1
for t in "$test_regex[@]"; do
[[ $1 =~ $t ]] && matched=0; break;
done
return "$matched"
test_regex=('^aa' '^abc' '^3@3' '>')
if check_func 'aaIsAMatch'; then
echo "A match was found"
fi
The function could be further improved to use the name of a variable (instead of a value) as the first argument.
posix
As there is no regex in posix shells and the only way to test is a case statement, we must use a case statement. Sadly, for older shells ([no extended globs available][1]) we must loop to make all tests. And, the globs need to be:
'aa*' 'abc*' '3@3*' '*>*'
An script example that tests several input strings against several globs:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; #break;; esac
echo "matched $value with $t"
;;
esac
done
return "$matched"
for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
echo "========A match was found for "$var""
fi
done
A simpler version of the function to exactly match your request:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; break;; esac
done
return "$matched"
add a comment |
Revised based on clarification to the question:
This is less elegant (and much less flexible),
but more compact than the other answers,
check_func() abc*
This returns true for aardvark
, abcdef
, 3@3com.com
and 12>5
.
And, of course, also aard>vark
, abc<def>ghi
and 3@3>3
.
add a comment |
Here's what the case
statement does: take the second parameter to the function ($2
). If it matches the pattern "$1"*
, i.e. the first argument to the function followed by anything, then execute true
and end the case
statement. true
does nothing and returns the status 0. Otherwise, if it matches *
, i.e. anything, execute false
and end the case
statement. false
does nothing and returns the status 1. Thus the case
statement has the status 0 if the second parameter starts with the first parameter and 1 otherwise. Since this is the last (and only) statement in the function, the function returns 0 if the second parameter starts with the first parameter and 1 otherwise.
Conditional statements such as if
in the shell consider a statement to be true if it returns 0 and false otherwise. Hence if beginswith "$var" "string"; then echo yes; else echo no; fi
prints yes
if the value of var
starts with string
and no
otherwise.
There are several alternative ways to write this function. For example the author could have used return 0
or return 1
instead of true
and false
, since they are the last statement in the function. The way the function was written makes it possible to use its body directly without wrapping it in a function, by just changing references to the function parameters ($1
and $2
) to whatever strings you want to work with.
To allow multiple prefixes, iterate over them in a loop. As soon as you've found a matching prefix, return from the function, with a true status (0). If none of the prefixes match, return a false status (conventionally 1).
# begins_with STRING PREFIX1 PREFIX2...
# Test if STRING starts with any of PREFIX1, PREFIX2, ...
begins_with ()
string=$1
shift
for prefix in "$@"; do
case "$string" in
"$prefix"*) return 0;;
esac
done
return 1
if begins_with "$var" 'aa' 'abc' '3@3'; then
echo "The value starts with one of the permitted prefixes"
fi
To test for a suffix, use the pattern *"$suffix"
instead of "$prefix"*
. To test for a substring, use *"$substring"*
. Note that the double quotes are necessary here, otherwise the variable would be interpreted as a pattern. For example:
suffix='?'
case "$var" in
*"$suffix") echo "The value of var ends with a question mark";;
esac
case "$var" in
*$suffix) echo "The value of var is not empty";;
esac
add a comment |
For anything involving text manipulation, Python is going to be far easier to write in:
check_func()
python -c "from sys import exit; exit(0) if any(['$1'.startswith(x) for x in ('aa', 'abc', '3@3')]) and '>' in '$1' else exit(1)"
I use it for all my bash scripts now even the kind that call lots of other programs and reads their results. It's just so much easier and doesn't suffer from weird errors like Bash seems too.
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
No Imaginatition is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f523625%2fwrite-a-function-that-checks-if-a-string-starts-with-or-contains-something%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
check_prefixes ()
value=$1
for prefix in aa abc 3@3; do
case $value in
"$prefix"*) return 0
esac
done
return 1
check_contains_gt ()
value=$1
case $value in
*">"*) return 0
esac
return 1
var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
printf '"%s" contains ">" and starts with one of the prefixesn' "$var"
fi
I divided the tests up into two functions. Both use case ... esac
and returns success (zero) as soon as this can be determined. If nothing matches, failure (1) is returned.
To make the list of prefixes more of a dynamic list, one could possibly write the first function as
check_prefixes ()
value=$1
shift
for prefix do
case $value in
"$prefix"*) return 0
esac
done
return 1
(the value to inspect is the first argument, which we save in value
and then shift
off the list of arguments to the function; we then iterate over the remaining arguments) and then call it as
check_prefixes "$var" aa abc 3@3
The second function could be changed in a similar manner, into
check_contains ()
value=$1
shift
case $value in
*"$1"*) return 0
esac
return 1
(to check for some arbitrary substring), or
check_contains_oneof ()
value=$1
shift
for substring do
case $value in
*"$substring"*) return 0
esac
done
return 1
(to check for any of a number of substrings)
Thanks. My intended logic is with a logical or instead of a logical and. Should it bevalue
instead ofvar
in the first function's definition?
– No Imaginatition
5 hours ago
@NoImaginatition OK, just change the logic in the code calling the functions (||
instead of&&
). Yes, that's a typo in my code, I'll fix it at once, thanks.
– Kusalananda♦
5 hours ago
I'm trying to combine both functions into one by definingcheck_func()
, but it won't work forecho a >file
. Any idea why?
– No Imaginatition
5 hours ago
@NoImaginatition Always double quote variable expansions ("$1"
) unless you know exactly in what contexts this is not needed.
– Kusalananda♦
5 hours ago
Great, it worked. If it's not much to ask, what is it that it makes it fail without the double quotes? I tried to test if it would expand the second call of$1
, and it seems to expand. I tested it withtest () echo $1 $1;
and it worked fine.
– No Imaginatition
5 hours ago
add a comment |
check_prefixes ()
value=$1
for prefix in aa abc 3@3; do
case $value in
"$prefix"*) return 0
esac
done
return 1
check_contains_gt ()
value=$1
case $value in
*">"*) return 0
esac
return 1
var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
printf '"%s" contains ">" and starts with one of the prefixesn' "$var"
fi
I divided the tests up into two functions. Both use case ... esac
and returns success (zero) as soon as this can be determined. If nothing matches, failure (1) is returned.
To make the list of prefixes more of a dynamic list, one could possibly write the first function as
check_prefixes ()
value=$1
shift
for prefix do
case $value in
"$prefix"*) return 0
esac
done
return 1
(the value to inspect is the first argument, which we save in value
and then shift
off the list of arguments to the function; we then iterate over the remaining arguments) and then call it as
check_prefixes "$var" aa abc 3@3
The second function could be changed in a similar manner, into
check_contains ()
value=$1
shift
case $value in
*"$1"*) return 0
esac
return 1
(to check for some arbitrary substring), or
check_contains_oneof ()
value=$1
shift
for substring do
case $value in
*"$substring"*) return 0
esac
done
return 1
(to check for any of a number of substrings)
Thanks. My intended logic is with a logical or instead of a logical and. Should it bevalue
instead ofvar
in the first function's definition?
– No Imaginatition
5 hours ago
@NoImaginatition OK, just change the logic in the code calling the functions (||
instead of&&
). Yes, that's a typo in my code, I'll fix it at once, thanks.
– Kusalananda♦
5 hours ago
I'm trying to combine both functions into one by definingcheck_func()
, but it won't work forecho a >file
. Any idea why?
– No Imaginatition
5 hours ago
@NoImaginatition Always double quote variable expansions ("$1"
) unless you know exactly in what contexts this is not needed.
– Kusalananda♦
5 hours ago
Great, it worked. If it's not much to ask, what is it that it makes it fail without the double quotes? I tried to test if it would expand the second call of$1
, and it seems to expand. I tested it withtest () echo $1 $1;
and it worked fine.
– No Imaginatition
5 hours ago
add a comment |
check_prefixes ()
value=$1
for prefix in aa abc 3@3; do
case $value in
"$prefix"*) return 0
esac
done
return 1
check_contains_gt ()
value=$1
case $value in
*">"*) return 0
esac
return 1
var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
printf '"%s" contains ">" and starts with one of the prefixesn' "$var"
fi
I divided the tests up into two functions. Both use case ... esac
and returns success (zero) as soon as this can be determined. If nothing matches, failure (1) is returned.
To make the list of prefixes more of a dynamic list, one could possibly write the first function as
check_prefixes ()
value=$1
shift
for prefix do
case $value in
"$prefix"*) return 0
esac
done
return 1
(the value to inspect is the first argument, which we save in value
and then shift
off the list of arguments to the function; we then iterate over the remaining arguments) and then call it as
check_prefixes "$var" aa abc 3@3
The second function could be changed in a similar manner, into
check_contains ()
value=$1
shift
case $value in
*"$1"*) return 0
esac
return 1
(to check for some arbitrary substring), or
check_contains_oneof ()
value=$1
shift
for substring do
case $value in
*"$substring"*) return 0
esac
done
return 1
(to check for any of a number of substrings)
check_prefixes ()
value=$1
for prefix in aa abc 3@3; do
case $value in
"$prefix"*) return 0
esac
done
return 1
check_contains_gt ()
value=$1
case $value in
*">"*) return 0
esac
return 1
var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
printf '"%s" contains ">" and starts with one of the prefixesn' "$var"
fi
I divided the tests up into two functions. Both use case ... esac
and returns success (zero) as soon as this can be determined. If nothing matches, failure (1) is returned.
To make the list of prefixes more of a dynamic list, one could possibly write the first function as
check_prefixes ()
value=$1
shift
for prefix do
case $value in
"$prefix"*) return 0
esac
done
return 1
(the value to inspect is the first argument, which we save in value
and then shift
off the list of arguments to the function; we then iterate over the remaining arguments) and then call it as
check_prefixes "$var" aa abc 3@3
The second function could be changed in a similar manner, into
check_contains ()
value=$1
shift
case $value in
*"$1"*) return 0
esac
return 1
(to check for some arbitrary substring), or
check_contains_oneof ()
value=$1
shift
for substring do
case $value in
*"$substring"*) return 0
esac
done
return 1
(to check for any of a number of substrings)
edited 5 hours ago
answered 8 hours ago
Kusalananda♦Kusalananda
150k18286471
150k18286471
Thanks. My intended logic is with a logical or instead of a logical and. Should it bevalue
instead ofvar
in the first function's definition?
– No Imaginatition
5 hours ago
@NoImaginatition OK, just change the logic in the code calling the functions (||
instead of&&
). Yes, that's a typo in my code, I'll fix it at once, thanks.
– Kusalananda♦
5 hours ago
I'm trying to combine both functions into one by definingcheck_func()
, but it won't work forecho a >file
. Any idea why?
– No Imaginatition
5 hours ago
@NoImaginatition Always double quote variable expansions ("$1"
) unless you know exactly in what contexts this is not needed.
– Kusalananda♦
5 hours ago
Great, it worked. If it's not much to ask, what is it that it makes it fail without the double quotes? I tried to test if it would expand the second call of$1
, and it seems to expand. I tested it withtest () echo $1 $1;
and it worked fine.
– No Imaginatition
5 hours ago
add a comment |
Thanks. My intended logic is with a logical or instead of a logical and. Should it bevalue
instead ofvar
in the first function's definition?
– No Imaginatition
5 hours ago
@NoImaginatition OK, just change the logic in the code calling the functions (||
instead of&&
). Yes, that's a typo in my code, I'll fix it at once, thanks.
– Kusalananda♦
5 hours ago
I'm trying to combine both functions into one by definingcheck_func()
, but it won't work forecho a >file
. Any idea why?
– No Imaginatition
5 hours ago
@NoImaginatition Always double quote variable expansions ("$1"
) unless you know exactly in what contexts this is not needed.
– Kusalananda♦
5 hours ago
Great, it worked. If it's not much to ask, what is it that it makes it fail without the double quotes? I tried to test if it would expand the second call of$1
, and it seems to expand. I tested it withtest () echo $1 $1;
and it worked fine.
– No Imaginatition
5 hours ago
Thanks. My intended logic is with a logical or instead of a logical and. Should it be
value
instead of var
in the first function's definition?– No Imaginatition
5 hours ago
Thanks. My intended logic is with a logical or instead of a logical and. Should it be
value
instead of var
in the first function's definition?– No Imaginatition
5 hours ago
@NoImaginatition OK, just change the logic in the code calling the functions (
||
instead of &&
). Yes, that's a typo in my code, I'll fix it at once, thanks.– Kusalananda♦
5 hours ago
@NoImaginatition OK, just change the logic in the code calling the functions (
||
instead of &&
). Yes, that's a typo in my code, I'll fix it at once, thanks.– Kusalananda♦
5 hours ago
I'm trying to combine both functions into one by defining
check_func()
, but it won't work for echo a >file
. Any idea why?– No Imaginatition
5 hours ago
I'm trying to combine both functions into one by defining
check_func()
, but it won't work for echo a >file
. Any idea why?– No Imaginatition
5 hours ago
@NoImaginatition Always double quote variable expansions (
"$1"
) unless you know exactly in what contexts this is not needed.– Kusalananda♦
5 hours ago
@NoImaginatition Always double quote variable expansions (
"$1"
) unless you know exactly in what contexts this is not needed.– Kusalananda♦
5 hours ago
Great, it worked. If it's not much to ask, what is it that it makes it fail without the double quotes? I tried to test if it would expand the second call of
$1
, and it seems to expand. I tested it with test () echo $1 $1;
and it worked fine.– No Imaginatition
5 hours ago
Great, it worked. If it's not much to ask, what is it that it makes it fail without the double quotes? I tried to test if it would expand the second call of
$1
, and it seems to expand. I tested it with test () echo $1 $1;
and it worked fine.– No Imaginatition
5 hours ago
add a comment |
For bash:
Using the properties of regex you can write start
with ^
and contain
by nothing.
The list of regexes to check start with aa
abc
or 3@3
and contains >
is:
^aa ^abc ^3@3 >
Make that a properly quoted list and ask bash to use regexes (=~
):
check_func()
matched=1
for test_regex in '^aa' '^abc' '^3@3' '>'; do
if [[ $var =~ $test_regex ]] ; then
matched=0
break
fi
done
return "$matched"
var='aaIsAMatch'
if check_func; then
echo "A match was found"
fi
The function has hard-coded the list of matches and the name of the var.
Giving the list of regex in an array variable and the value to test on the first argument:
check_func()
local matched; matched=1
for t in "$test_regex[@]"; do
[[ $1 =~ $t ]] && matched=0; break;
done
return "$matched"
test_regex=('^aa' '^abc' '^3@3' '>')
if check_func 'aaIsAMatch'; then
echo "A match was found"
fi
The function could be further improved to use the name of a variable (instead of a value) as the first argument.
posix
As there is no regex in posix shells and the only way to test is a case statement, we must use a case statement. Sadly, for older shells ([no extended globs available][1]) we must loop to make all tests. And, the globs need to be:
'aa*' 'abc*' '3@3*' '*>*'
An script example that tests several input strings against several globs:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; #break;; esac
echo "matched $value with $t"
;;
esac
done
return "$matched"
for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
echo "========A match was found for "$var""
fi
done
A simpler version of the function to exactly match your request:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; break;; esac
done
return "$matched"
add a comment |
For bash:
Using the properties of regex you can write start
with ^
and contain
by nothing.
The list of regexes to check start with aa
abc
or 3@3
and contains >
is:
^aa ^abc ^3@3 >
Make that a properly quoted list and ask bash to use regexes (=~
):
check_func()
matched=1
for test_regex in '^aa' '^abc' '^3@3' '>'; do
if [[ $var =~ $test_regex ]] ; then
matched=0
break
fi
done
return "$matched"
var='aaIsAMatch'
if check_func; then
echo "A match was found"
fi
The function has hard-coded the list of matches and the name of the var.
Giving the list of regex in an array variable and the value to test on the first argument:
check_func()
local matched; matched=1
for t in "$test_regex[@]"; do
[[ $1 =~ $t ]] && matched=0; break;
done
return "$matched"
test_regex=('^aa' '^abc' '^3@3' '>')
if check_func 'aaIsAMatch'; then
echo "A match was found"
fi
The function could be further improved to use the name of a variable (instead of a value) as the first argument.
posix
As there is no regex in posix shells and the only way to test is a case statement, we must use a case statement. Sadly, for older shells ([no extended globs available][1]) we must loop to make all tests. And, the globs need to be:
'aa*' 'abc*' '3@3*' '*>*'
An script example that tests several input strings against several globs:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; #break;; esac
echo "matched $value with $t"
;;
esac
done
return "$matched"
for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
echo "========A match was found for "$var""
fi
done
A simpler version of the function to exactly match your request:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; break;; esac
done
return "$matched"
add a comment |
For bash:
Using the properties of regex you can write start
with ^
and contain
by nothing.
The list of regexes to check start with aa
abc
or 3@3
and contains >
is:
^aa ^abc ^3@3 >
Make that a properly quoted list and ask bash to use regexes (=~
):
check_func()
matched=1
for test_regex in '^aa' '^abc' '^3@3' '>'; do
if [[ $var =~ $test_regex ]] ; then
matched=0
break
fi
done
return "$matched"
var='aaIsAMatch'
if check_func; then
echo "A match was found"
fi
The function has hard-coded the list of matches and the name of the var.
Giving the list of regex in an array variable and the value to test on the first argument:
check_func()
local matched; matched=1
for t in "$test_regex[@]"; do
[[ $1 =~ $t ]] && matched=0; break;
done
return "$matched"
test_regex=('^aa' '^abc' '^3@3' '>')
if check_func 'aaIsAMatch'; then
echo "A match was found"
fi
The function could be further improved to use the name of a variable (instead of a value) as the first argument.
posix
As there is no regex in posix shells and the only way to test is a case statement, we must use a case statement. Sadly, for older shells ([no extended globs available][1]) we must loop to make all tests. And, the globs need to be:
'aa*' 'abc*' '3@3*' '*>*'
An script example that tests several input strings against several globs:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; #break;; esac
echo "matched $value with $t"
;;
esac
done
return "$matched"
for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
echo "========A match was found for "$var""
fi
done
A simpler version of the function to exactly match your request:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; break;; esac
done
return "$matched"
For bash:
Using the properties of regex you can write start
with ^
and contain
by nothing.
The list of regexes to check start with aa
abc
or 3@3
and contains >
is:
^aa ^abc ^3@3 >
Make that a properly quoted list and ask bash to use regexes (=~
):
check_func()
matched=1
for test_regex in '^aa' '^abc' '^3@3' '>'; do
if [[ $var =~ $test_regex ]] ; then
matched=0
break
fi
done
return "$matched"
var='aaIsAMatch'
if check_func; then
echo "A match was found"
fi
The function has hard-coded the list of matches and the name of the var.
Giving the list of regex in an array variable and the value to test on the first argument:
check_func()
local matched; matched=1
for t in "$test_regex[@]"; do
[[ $1 =~ $t ]] && matched=0; break;
done
return "$matched"
test_regex=('^aa' '^abc' '^3@3' '>')
if check_func 'aaIsAMatch'; then
echo "A match was found"
fi
The function could be further improved to use the name of a variable (instead of a value) as the first argument.
posix
As there is no regex in posix shells and the only way to test is a case statement, we must use a case statement. Sadly, for older shells ([no extended globs available][1]) we must loop to make all tests. And, the globs need to be:
'aa*' 'abc*' '3@3*' '*>*'
An script example that tests several input strings against several globs:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; #break;; esac
echo "matched $value with $t"
;;
esac
done
return "$matched"
for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
echo "========A match was found for "$var""
fi
done
A simpler version of the function to exactly match your request:
check_func() :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; break;; esac
done
return "$matched"
edited 7 hours ago
answered 8 hours ago
IsaacIsaac
13k12159
13k12159
add a comment |
add a comment |
Revised based on clarification to the question:
This is less elegant (and much less flexible),
but more compact than the other answers,
check_func() abc*
This returns true for aardvark
, abcdef
, 3@3com.com
and 12>5
.
And, of course, also aard>vark
, abc<def>ghi
and 3@3>3
.
add a comment |
Revised based on clarification to the question:
This is less elegant (and much less flexible),
but more compact than the other answers,
check_func() abc*
This returns true for aardvark
, abcdef
, 3@3com.com
and 12>5
.
And, of course, also aard>vark
, abc<def>ghi
and 3@3>3
.
add a comment |
Revised based on clarification to the question:
This is less elegant (and much less flexible),
but more compact than the other answers,
check_func() abc*
This returns true for aardvark
, abcdef
, 3@3com.com
and 12>5
.
And, of course, also aard>vark
, abc<def>ghi
and 3@3>3
.
Revised based on clarification to the question:
This is less elegant (and much less flexible),
but more compact than the other answers,
check_func() abc*
This returns true for aardvark
, abcdef
, 3@3com.com
and 12>5
.
And, of course, also aard>vark
, abc<def>ghi
and 3@3>3
.
edited 5 hours ago
answered 8 hours ago
G-ManG-Man
14.6k94175
14.6k94175
add a comment |
add a comment |
Here's what the case
statement does: take the second parameter to the function ($2
). If it matches the pattern "$1"*
, i.e. the first argument to the function followed by anything, then execute true
and end the case
statement. true
does nothing and returns the status 0. Otherwise, if it matches *
, i.e. anything, execute false
and end the case
statement. false
does nothing and returns the status 1. Thus the case
statement has the status 0 if the second parameter starts with the first parameter and 1 otherwise. Since this is the last (and only) statement in the function, the function returns 0 if the second parameter starts with the first parameter and 1 otherwise.
Conditional statements such as if
in the shell consider a statement to be true if it returns 0 and false otherwise. Hence if beginswith "$var" "string"; then echo yes; else echo no; fi
prints yes
if the value of var
starts with string
and no
otherwise.
There are several alternative ways to write this function. For example the author could have used return 0
or return 1
instead of true
and false
, since they are the last statement in the function. The way the function was written makes it possible to use its body directly without wrapping it in a function, by just changing references to the function parameters ($1
and $2
) to whatever strings you want to work with.
To allow multiple prefixes, iterate over them in a loop. As soon as you've found a matching prefix, return from the function, with a true status (0). If none of the prefixes match, return a false status (conventionally 1).
# begins_with STRING PREFIX1 PREFIX2...
# Test if STRING starts with any of PREFIX1, PREFIX2, ...
begins_with ()
string=$1
shift
for prefix in "$@"; do
case "$string" in
"$prefix"*) return 0;;
esac
done
return 1
if begins_with "$var" 'aa' 'abc' '3@3'; then
echo "The value starts with one of the permitted prefixes"
fi
To test for a suffix, use the pattern *"$suffix"
instead of "$prefix"*
. To test for a substring, use *"$substring"*
. Note that the double quotes are necessary here, otherwise the variable would be interpreted as a pattern. For example:
suffix='?'
case "$var" in
*"$suffix") echo "The value of var ends with a question mark";;
esac
case "$var" in
*$suffix) echo "The value of var is not empty";;
esac
add a comment |
Here's what the case
statement does: take the second parameter to the function ($2
). If it matches the pattern "$1"*
, i.e. the first argument to the function followed by anything, then execute true
and end the case
statement. true
does nothing and returns the status 0. Otherwise, if it matches *
, i.e. anything, execute false
and end the case
statement. false
does nothing and returns the status 1. Thus the case
statement has the status 0 if the second parameter starts with the first parameter and 1 otherwise. Since this is the last (and only) statement in the function, the function returns 0 if the second parameter starts with the first parameter and 1 otherwise.
Conditional statements such as if
in the shell consider a statement to be true if it returns 0 and false otherwise. Hence if beginswith "$var" "string"; then echo yes; else echo no; fi
prints yes
if the value of var
starts with string
and no
otherwise.
There are several alternative ways to write this function. For example the author could have used return 0
or return 1
instead of true
and false
, since they are the last statement in the function. The way the function was written makes it possible to use its body directly without wrapping it in a function, by just changing references to the function parameters ($1
and $2
) to whatever strings you want to work with.
To allow multiple prefixes, iterate over them in a loop. As soon as you've found a matching prefix, return from the function, with a true status (0). If none of the prefixes match, return a false status (conventionally 1).
# begins_with STRING PREFIX1 PREFIX2...
# Test if STRING starts with any of PREFIX1, PREFIX2, ...
begins_with ()
string=$1
shift
for prefix in "$@"; do
case "$string" in
"$prefix"*) return 0;;
esac
done
return 1
if begins_with "$var" 'aa' 'abc' '3@3'; then
echo "The value starts with one of the permitted prefixes"
fi
To test for a suffix, use the pattern *"$suffix"
instead of "$prefix"*
. To test for a substring, use *"$substring"*
. Note that the double quotes are necessary here, otherwise the variable would be interpreted as a pattern. For example:
suffix='?'
case "$var" in
*"$suffix") echo "The value of var ends with a question mark";;
esac
case "$var" in
*$suffix) echo "The value of var is not empty";;
esac
add a comment |
Here's what the case
statement does: take the second parameter to the function ($2
). If it matches the pattern "$1"*
, i.e. the first argument to the function followed by anything, then execute true
and end the case
statement. true
does nothing and returns the status 0. Otherwise, if it matches *
, i.e. anything, execute false
and end the case
statement. false
does nothing and returns the status 1. Thus the case
statement has the status 0 if the second parameter starts with the first parameter and 1 otherwise. Since this is the last (and only) statement in the function, the function returns 0 if the second parameter starts with the first parameter and 1 otherwise.
Conditional statements such as if
in the shell consider a statement to be true if it returns 0 and false otherwise. Hence if beginswith "$var" "string"; then echo yes; else echo no; fi
prints yes
if the value of var
starts with string
and no
otherwise.
There are several alternative ways to write this function. For example the author could have used return 0
or return 1
instead of true
and false
, since they are the last statement in the function. The way the function was written makes it possible to use its body directly without wrapping it in a function, by just changing references to the function parameters ($1
and $2
) to whatever strings you want to work with.
To allow multiple prefixes, iterate over them in a loop. As soon as you've found a matching prefix, return from the function, with a true status (0). If none of the prefixes match, return a false status (conventionally 1).
# begins_with STRING PREFIX1 PREFIX2...
# Test if STRING starts with any of PREFIX1, PREFIX2, ...
begins_with ()
string=$1
shift
for prefix in "$@"; do
case "$string" in
"$prefix"*) return 0;;
esac
done
return 1
if begins_with "$var" 'aa' 'abc' '3@3'; then
echo "The value starts with one of the permitted prefixes"
fi
To test for a suffix, use the pattern *"$suffix"
instead of "$prefix"*
. To test for a substring, use *"$substring"*
. Note that the double quotes are necessary here, otherwise the variable would be interpreted as a pattern. For example:
suffix='?'
case "$var" in
*"$suffix") echo "The value of var ends with a question mark";;
esac
case "$var" in
*$suffix) echo "The value of var is not empty";;
esac
Here's what the case
statement does: take the second parameter to the function ($2
). If it matches the pattern "$1"*
, i.e. the first argument to the function followed by anything, then execute true
and end the case
statement. true
does nothing and returns the status 0. Otherwise, if it matches *
, i.e. anything, execute false
and end the case
statement. false
does nothing and returns the status 1. Thus the case
statement has the status 0 if the second parameter starts with the first parameter and 1 otherwise. Since this is the last (and only) statement in the function, the function returns 0 if the second parameter starts with the first parameter and 1 otherwise.
Conditional statements such as if
in the shell consider a statement to be true if it returns 0 and false otherwise. Hence if beginswith "$var" "string"; then echo yes; else echo no; fi
prints yes
if the value of var
starts with string
and no
otherwise.
There are several alternative ways to write this function. For example the author could have used return 0
or return 1
instead of true
and false
, since they are the last statement in the function. The way the function was written makes it possible to use its body directly without wrapping it in a function, by just changing references to the function parameters ($1
and $2
) to whatever strings you want to work with.
To allow multiple prefixes, iterate over them in a loop. As soon as you've found a matching prefix, return from the function, with a true status (0). If none of the prefixes match, return a false status (conventionally 1).
# begins_with STRING PREFIX1 PREFIX2...
# Test if STRING starts with any of PREFIX1, PREFIX2, ...
begins_with ()
string=$1
shift
for prefix in "$@"; do
case "$string" in
"$prefix"*) return 0;;
esac
done
return 1
if begins_with "$var" 'aa' 'abc' '3@3'; then
echo "The value starts with one of the permitted prefixes"
fi
To test for a suffix, use the pattern *"$suffix"
instead of "$prefix"*
. To test for a substring, use *"$substring"*
. Note that the double quotes are necessary here, otherwise the variable would be interpreted as a pattern. For example:
suffix='?'
case "$var" in
*"$suffix") echo "The value of var ends with a question mark";;
esac
case "$var" in
*$suffix) echo "The value of var is not empty";;
esac
answered 8 hours ago
GillesGilles
557k13411431654
557k13411431654
add a comment |
add a comment |
For anything involving text manipulation, Python is going to be far easier to write in:
check_func()
python -c "from sys import exit; exit(0) if any(['$1'.startswith(x) for x in ('aa', 'abc', '3@3')]) and '>' in '$1' else exit(1)"
I use it for all my bash scripts now even the kind that call lots of other programs and reads their results. It's just so much easier and doesn't suffer from weird errors like Bash seems too.
add a comment |
For anything involving text manipulation, Python is going to be far easier to write in:
check_func()
python -c "from sys import exit; exit(0) if any(['$1'.startswith(x) for x in ('aa', 'abc', '3@3')]) and '>' in '$1' else exit(1)"
I use it for all my bash scripts now even the kind that call lots of other programs and reads their results. It's just so much easier and doesn't suffer from weird errors like Bash seems too.
add a comment |
For anything involving text manipulation, Python is going to be far easier to write in:
check_func()
python -c "from sys import exit; exit(0) if any(['$1'.startswith(x) for x in ('aa', 'abc', '3@3')]) and '>' in '$1' else exit(1)"
I use it for all my bash scripts now even the kind that call lots of other programs and reads their results. It's just so much easier and doesn't suffer from weird errors like Bash seems too.
For anything involving text manipulation, Python is going to be far easier to write in:
check_func()
python -c "from sys import exit; exit(0) if any(['$1'.startswith(x) for x in ('aa', 'abc', '3@3')]) and '>' in '$1' else exit(1)"
I use it for all my bash scripts now even the kind that call lots of other programs and reads their results. It's just so much easier and doesn't suffer from weird errors like Bash seems too.
edited 5 hours ago
answered 5 hours ago
BenjaminBenjamin
765
765
add a comment |
add a comment |
No Imaginatition is a new contributor. Be nice, and check out our Code of Conduct.
No Imaginatition is a new contributor. Be nice, and check out our Code of Conduct.
No Imaginatition is a new contributor. Be nice, and check out our Code of Conduct.
No Imaginatition is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f523625%2fwrite-a-function-that-checks-if-a-string-starts-with-or-contains-something%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
It just occurred to me that your question is ambiguous. Do you mean (1) I want to check if
var
starts withaa
. I want to check ifvar
starts withabc
. I want to check ifvar
starts with3@3
. And I want to check ifvar
contains>
. ? Or do you mean (2) I want to check ifvar
starts withaa
,abc
or3@3
, and it also contains>
. ?– G-Man
7 hours ago
@G-Man The first one. Thanks for bringing that up.
– No Imaginatition
6 hours ago