18

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?

Squidly
  • 2,707
  • 19
  • 43
moorara
  • 3,897
  • 10
  • 47
  • 60
  • Does this answer your question? [How to check pattern match by using /bin/sh, not by /bin/bash](https://stackoverflow.com/questions/21115121/how-to-check-pattern-match-by-using-bin-sh-not-by-bin-bash) – Victor Sergienko Mar 11 '20 at 18:17

2 Answers2

21

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
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 2
    I would go with `printf` over `echo -n`, which is non-standard. – Tom Fenech Jun 04 '15 at 15:22
  • Thanks. How should I write `if [[ -n $1 ]]; then` in sh? – moorara Jun 04 '15 at 15:23
  • 1
    It would be `if [ -n "$1" ]` in `/bin/sh` – anubhava Jun 04 '15 at 15:23
  • 1
    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.) – sjnarv Jun 04 '15 at 15:26
  • 1
    It worked well. I only realized that the `-` should also be double quoted as follows: `'^[a-z0-9_"-"]+@[a-z0-9_"-."]+:'` – moorara Jun 04 '15 at 15:37
  • 1
    @moorara `-` can be included in a character class without additional quoting by putting it first, like: `'^[-a-z0-9_-]+@[-a-z0-9_.]+:'` – Henk Langeveld Jun 05 '15 at 09:00
4

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

Henk Langeveld
  • 8,088
  • 1
  • 43
  • 57
  • 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")` – Vincent Yin Apr 01 '22 at 20:29
  • 1
    @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. – Henk Langeveld Apr 03 '22 at 09:49