I’m trying to check if the user input $1 exist in an array. And here is my code:
array=( aaa.bbb.ccc ccc.ddd.aaa ) echo ${array[@]} | grep -o -w "$1"
What I expect is only “aaa.bbb.ccc” or “ccc.ddd.aaa” can be found. However, in this case, like “aaa” or “ccc” can also pass the validation. Seems like the dot is not treated as part of the string.
Should I use regex or other grep option?
Advertisement
Answer
It sounds like you want:
- literal string matching
- against entire input lines.
Therefore, use -F
(for literal matching) and -x
for whole-line matching:
array=( aaa.bbb.ccc ccc.ddd.aaa ) printf '%sn' "${array[@]}" | grep -Fx "$1"
Now, only literal strings aaa.bbb.ccc
and ccc.ddd.aaa
will match, not substrings such as aaa
.
Since you’re matching the entire line, use of -o
(to only output the matching part of each line) is unnecessary.
Also note how printf '%sn' "${array[@]}"
must be used to print each array element on its own line, whereas echo ${array[@]}
prints the elements on a single line (with whitespace normalization due to word-splitting and potential globbing applied, because ${array[@]}
is not enclosed in "..."
).
The problem with your approach:
grep
defaults to (basic) regular expressions, so a$1
value containing.
would result in that.
being interpreted to mean “any single character”.echo ${array[@]}
is problematic due to potentially unwanted whitespace normalization and globbing, as stated;echo "${array[@]}" | grep -Fwo "$1"
would be an improvement, but bears a slight risk of false positives.