2

I am trying to compare a string with the $ character, followed by either s or t and a range of numbers. but the range is different for each letter. for example if it is an s it can be followed by numbers between 0-7 and if it is a t it can be followed by numbers between 0-9.

What I managed to write a part of the if statement to compare it, but I couldn't figure out how to include different ranges for each letter

script:

#!/bin/bash
input="test1.txt"
check(){
    while read -r line; do
      a=( $line )
      for i in "${a[@]:1}"; do
         if [[ "$i" == \$[st]* ]]; then
             echo "$i"
         fi
      done
    done < "$input"
}
check

Instead of using * I want to specify for s that it can only be followed by numbers between 0-7 and t can only be followed by numbers 0-9. I tried using this:

if [[ "$i" == \$(s[0-7]*|t[0-9]*) ]]; then

but I got this error:

./test.sh: line 9: syntax error in conditional expression: unexpected token `('                                         ./test.sh: line 9: syntax error near `\$(s'                                                                             ./test.sh: line 9: `if [[ "$i" == \$(s[0-7]*|t[0-9]*) ]]; then'  
1
  • 1
    Note that a=( $line ) is a dangerous practice for the reasons described in BashPitfalls #50 (while the pitfall refers to command substitutions, unquoted parameter expansions behave identically for purposes thereof) -- better to make it while read -r -a a; do and have read split the words of your line into array elements itself. Commented Mar 28, 2019 at 15:02

2 Answers 2

7

=~ is used for regex matching, not ==. Correct that and use a pipe (|) in your regex, which means OR.

if [[ $i =~ \$(s[0-7]*|t[0-9]*) ]]
Sign up to request clarification or add additional context in comments.

3 Comments

@David, also note that =~ is a bash-specific feature, so you cannot run your code like sh ./myscript
Personally, I would use [$] rather than \$ -- it's a bit more robust across different quoting contexts/styles -- but that's a trivial quibble; this is a good solution either way.
If you really want to use ==, you can use the extended pattern [$]@(s*([0-7])|t*([0-9])) instead.
1

Why are you writing a script with a loop for this? It can simply be done using a grep, as you can see in this example:

Prompt>cat test1.txt
s1
s8
t1
t8
Prompt> grep -E "s[0-7]|t[0-9]" test1.txt
s1
t1
t8

Explanation:

s[0-7] means the letter "s", followed by any digit from 0 to 7.
t[0-9] means the letter "t", followed by any digit from 0 to 9.

grep -E means "Extended regular expression".

A|B in the regular expression means The expression should contain A OR B (which is exactly the "extended" part of the regular expression).

1 Comment

FYI, your post was incorrectly flagged as "low quality". It has been handled accordingly. From Review.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.