How to write and match regular expressions in /bin/sh script?

20,407

Solution 1

You can use this equivalent script in /bin/sh:

if uname | grep -Eq '(QNX|qnx)'; then
   printf "what is the dev prefix to use? "
   read dev_prefix
   if echo "$dev_prefix" | grep -Eq '^[a-z0-9_-]+@[a-z0-9_-"."]+:'; then
   ...
   fi
fi

Solution 2

You can use shellcheck to detect non-Posix features in a script:

Copy/Paste this into https://www.shellcheck.net/:

#!/bin/sh
if [[ `1uname` =~ (QNX|qnx) ]]; then
  read -p "what is the dev prefix to use? " dev_prefix
  if [[ $dev_prefix =~ ^[a-z0-9_-]+@[a-z0-9_-"."]+:.*$ ]]; then
    : nothing
  fi
fi

Or install shellcheck locally, and run shellcheck ./check.sh, and it will highlight the non-posix features:

In ./check.sh line 2:
if [[ `1uname` =~ (QNX|qnx) ]]; then
   ^-- SC2039: In POSIX sh, [[ ]] is not supported.
      ^-- SC2006: Use $(..) instead of deprecated `..`

In ./check.sh line 4:
  if [[ $dev_prefix =~ ^[a-z0-9_-]+@[a-z0-9_-"."]+:.*$ ]]; then
     ^-- SC2039: In POSIX sh, [[ ]] is not supported.

You either have to rewrite the expressions as globs (not realistic), or use external commands (grep/awk), a explained by @anubhava

Share:
20,407

Related videos on Youtube

moorara
Author by

moorara

Updated on October 20, 2021

Comments

  • moorara
    moorara over 2 years

    I am writing a shell script for a limited unix-based microkernel which doesn't have bash! the /bin/sh can't run the following lines for some reasons.

    if [[ `uname` =~ (QNX|qnx) ]]; then
    read -p "what is the dev prefix to use? " dev_prefix
    if [[ $dev_prefix =~ ^[a-z0-9_-]+@[a-z0-9_-"."]+:.*$ ]]; then
    

    For the 1st and 3rd lines, it complains about missing expression operator, and for the 2nd line it says no coprocess! Can anyone shed light on differences between /bin/bash and /bin/sh scripts?

  • Tom Fenech
    Tom Fenech almost 9 years
    I would go with printf over echo -n, which is non-standard.
  • moorara
    moorara almost 9 years
    Thanks. How should I write if [[ -n $1 ]]; then in sh?
  • anubhava
    anubhava almost 9 years
    It would be if [ -n "$1" ] in /bin/sh
  • sjnarv
    sjnarv almost 9 years
    Good bash-to-sh conversion, which answers the core question (upvoted). I wonder if this "limted unix-based microkernel" may have an old grep too, requiring older RE forms. The printf command may not be present either. Anyone remember versions of echo that used \c ... ? (I clearly don't know QNX.)
  • moorara
    moorara almost 9 years
    It worked well. I only realized that the - should also be double quoted as follows: '^[a-z0-9_"-"]+@[a-z0-9_"-."]+:'
  • Henk Langeveld
    Henk Langeveld almost 9 years
    @moorara - can be included in a character class without additional quoting by putting it first, like: '^[-a-z0-9_-]+@[-a-z0-9_.]+:'
  • Vincent Yin
    Vincent Yin about 2 years
    That looks like bash syntax rather than Bourne shell (despite the #!/bin/sh -- maybe your /bin/sh is in fact bash?) I get this syntax error in a real Bourne shell (I think): sh: 4: Syntax error: "(" unexpected (expecting "then")
  • Henk Langeveld
    Henk Langeveld about 2 years
    @VincentYin - Correct. [[ ... ]] was introduced in ksh and bash. Your comment would have been more appropriate to the original question - it has no relevance to the use of shellcheck, which this answer advocates to check for POSIX compatibility.