3

In a shell script, I have a function afun that was passed a few arguments. I need another function that will help me find out if at least one of those arguments contains a given character which is not known a priori (but it could be any character like a, 9, *, \, |, /, (, [ and so on, but not space):

afun() {
  # Some commands here...
  testchar=... # here I have some logic which decides what character should be tested below
  # Now, call another function to test if any of the args to "afun"
  # contain the character in var "testchar".
  # If it does, print "Found character '$testchar' !"
}

The proposed function should be compatible at least with Bash, Dash, Ash and ZSH - because I have a script that needs to run under different Linux distros (Ubuntu, Alpine Linux) installed in Docker containers, and I don't want to declare a dependency on a specific shell interpreter since not all those containers will necessarily have it installed.

9
  • 3
    Bash, Dash, Ash and ZSH . That sounds like you're kidding. ;) And the question is not very clear.. Commented Jun 17, 2016 at 18:48
  • ZSH has more features than Ash, but is it unreasonable what I'm asking? And thanks, I've fixed the variable name (it should be testchar instead of c) Commented Jun 17, 2016 at 18:50
  • Not unreasonable, but should be very difficult IMHO.. :( Commented Jun 17, 2016 at 18:51
  • 3
    @Elifarley, it's not just "more features" -- ash, bash and ksh are compliant with POSIX sh (barring caveats like bash's support for echo -e), whereas zsh is intentionally incompatible with the standard (in places where its maintainers decided -- with some basis in fact -- that the standard enforces bad design decisions) unless running in non-default posix mode. That's not to say that writing scripts compatible with both zsh and POSIX-compliant shells can't be done, but it does mean that it requires a bit more care than the usual (ash+bash+ksh) practice of just complying with POSIX. Commented Jun 17, 2016 at 19:23
  • 1
    BTW, local is not defined by POSIX -- if you're going for maximal compatibility, you'll want to do without. Commented Jun 17, 2016 at 19:26

2 Answers 2

4

Here's my proposed shell function:

charexists() {
  char="$1"; shift
  case "$*" in *"$char"*) return;; esac; return 1
}

And here's how you can use it:

afun() {
  # Some commands here...
  testchar=... # here I have some logic which decides what character should be tested below
  # Now, call another function to test if any of the args to "afun"
  # contain the character in var "testchar".
  # If it does, print "Found character '$testchar' !"
  charexists "$testchar" "$@" && echo "Found character '$testchar' !"
}

Here's a simple unit test:

fun2test=charexists
{ $fun2test '*' 'a*b' && printf 1 ;} ; \
{ $fun2test '*' 'a' '*' '\' 'b#c|+' '\' && printf 2 ;} ;\
{ $fun2test '\' 'a' '*' '\' 'b#c|+' '\' && printf 3 ;} ;\
{ $fun2test '*' 'ab' || printf 4 ;} ; \
{ $fun2test '*' 'a' '' '/' 'b#c|+' '\' || printf 5 ;}; echo

It should print 12345 if all 5 tests pass.

I have just tested under Bash, Dash, Ash and ZSH and all went well.

Sign up to request clarification or add additional context in comments.

2 Comments

charexists "$testchar" $* -- without the $* quoted -- will behave badly if your list of arguments contains, say, * -- unless you want that to be expanded to a list of filenames in the current directory.
Indeed! Fixed, thanks!
-1

Below is my bash specific solution for this :

#!/bin/bash
fun()
{
  not_allowed=' ' # Charater which is not allowed
  [[ "$1" =~ $not_allowed ]] && echo "Character which is not allowed found"
}

fun "TestWithoutSpace"
fun "Test with space"

1 Comment

Using the test case found in my solution, your proposed solution only prints 34, so it fails the first 2 tests.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.