Here is my code
vmname="$1"
EXCEPTLIST="desktop-01|desktop-02|desktop-03|desktop-04"
if [[ $vmname != @(${EXCEPTLIST}) ]]; then
echo "${vmname}"
else
echo "Its in the exceptlist"
fi
The above code works perfectly but my question is , the EXCEPTLIST can be a long line, say 100 server names. In that case its hard to put all that names in one line. In that situation is there any way to make the variable EXCEPTLIST to be a multiline variable ? something like as follows:
EXCEPTLIST="desktop-01|desktop-02|desktop-03| \n
desktop-04|desktop-05|desktop-06| \n
desktop-07|desktop-08"
I am not sure but was thinking of possibilities.
Apparently I would like to know the terminology of using @(${})
- Is this called variable expansion or what ? Does anyone know the documentation/explain to me about how this works in bash. ?
CodePudding user response:
One can declare an array if the data/string is long/large. Use IFS
and printf
for the format string, something like:
#!/usr/bin/env bash
exceptlist=(
desktop-01
desktop-02
desktop-03
desktop-04
desktop-05
desktop-06
)
pattern=$(IFS='|'; printf '@(%s)' "${exceptlist[*]}")
[[ "$vmname" != $pattern ]] && echo good
In that situation is there any way to make the variable EXCEPTLIST to be a multiline variable ?
With your given input/data an array is also a best option, something like:
exceptlist=(
'desktop-01|desktop-02|desktop-03'
'desktop-04|desktop-05|desktop-06'
'desktop-07|desktop-08'
)
Check what is the value of $pattern
variable one way is:
declare -p pattern
Output:
declare -- pattern="@(desktop-01|desktop-02|desktop-03|desktop-04|desktop-05|desktop-06)"
Need to test/check if
$vmname
is an empty string too, since it will always be true.On a side note, don't use all upper case variables for purely internal purposes.
The
$(...)
is calledCommand Substitution
.- See
LESS= '/\ *Command Substitution' man bash
- See
In addition to what was mentioned in the comments about pattern matching
See
LESS= /'(pattern-list)' man bash
See
LESS= /' *\[\[ expression' man bash
CodePudding user response:
s there any way to make the variable EXCEPTLIST to be a multiline variable ?
I see no reason to use matching. Use a bash array and just compare.
exceptlist=(
desktop-01
desktop-02
desktop-03
desktop-04
desktop-05
desktop-06
)
is_in_list() {
local i
for i in "${@:2}"; do
if [[ "$1" = "$i" ]]; then
return 0
fi
done
return 1
}
if is_in_list "$vmname" "${EXCEPTLIST[@]}"; then
echo "is in exception list ${vmname}"
fi
@(${})- Is this called variable expansion or what ? Does anyone know the documentation/explain to me about how this works in bash. ?
${var}
is a variable expansion.
@(...)
are just characters @
(
)
.
From man bash
in Compund commands
:
[[ expression ]]
When the == and != operators are used, the string to the right of the operator is considered a pattern and matched according to the rules
described below under Pattern Matching, as if the extglob shell option were enabled. ...
From Pattern Matching
in man bash
:
@(pattern-list)
Matches one of the given patterns
[[
command receives the @(a|b|c)
string and then matches the arguments.
CodePudding user response:
There is absolutely no need to use Bash specific regex or arrays and loop for a match, if using grep
for raw string on word boundary.
The exception list can be multi-line, it will work as well:
#!/usr/bin/sh
exceptlist='
desktop-01|desktop-02|desktop-03|
deskop-04|desktop-05|desktop-06|
desktop-07|deskop-08'
if printf %s "$exceptlist" | grep -qwF "$1"; then
printf '%s is in the exceptlist\n' "$1"
fi
CodePudding user response:
I wouldn't bother with multiple lines of text. This is would be just fine:
EXCEPTLIST='desktop-01|desktop-02|desktop-03|'
EXCEPTLIST ='desktop-04|desktop-05|desktop-06|'
EXCEPTLIST ='desktop-07|desktop-08'
The @(...)
construct is called extended globbing pattern and what it does is an extension of what you probably already know -- wildcards:
VAR='foobar'
if [[ "$VAR" == fo?b* ]]; then
echo "Yes!"
else
echo "No!"
fi
A quick walkthrough on extended globbing examples: https://www.linuxjournal.com/content/bash-extended-globbing
CodePudding user response:
#!/bin/bash
set o posix
shopt -s extglob
vmname=$1
EXCEPTLIST=(
desktop-01 desktop-02 desktop-03
...
)
if IFS='|' eval '[[ ${vmname} == @(${EXCEPTLIST[*]}) ]]'; then
...
CodePudding user response:
There are multiple solutions to your problem.
Solution 1, since all the desktop has the same desktop-0
prefix and only differ in the last letter, we can make use of {,} or {..} expansion as follows:
vmname="$1"
found=0
for d in desktop-{01..08}
do
if [[ "$vmname" == $d ]]; then
found=1
break
fi
done
if (( found )); then
echo "It's in the exceptlist"
fi
Solution 2, sometimes, it is good to provide a list in a maintainable clear text list. We can use a while loop and iterate through the list
vmname="$1"
found=0
while IFS= read -r d
do
if [[ "$vmname" == $d ]]; then
found=1
break
fi
done <<EOF
desktop-01
desktop-02
desktop-03
desktop-04
desktop-05
desktop-06
desktop-07
desktop-08
EOF
if (( found )); then
echo "It's in the exceptlist"
fi
Solution 3, we can desktop the servers using regular expressions:
vmname="$1"
if [[ "$vmname" =~ ^desktop-0[1-8]$ ]]; then
echo "It's in the exceptlist"
fi
Solution 4, we populate an array, then iterate through an array:
vmname="$1"
exceptlist=()
exceptlist =(desktop-01 desktop-02 desktop-03 deskop-04)
exceptlist =(desktop-05 desktop-06 desktop-07 deskop-08)
found=0
for d in ${exceptlist[@]}
do
if [[ "$vmname" == "$d" ]]; then
found=1
break;
fi
done
if (( found )); then
echo "It's in the exceptlist"
fi