0

I'm trying to pass the second argument to get an array and loop trough but im getting this error: ${$2[@]}: bad substitution

my code is:

/etc/init.d/displaycameras start c1

    #!/bin/bash
    dis1cam1="screen -dmS dis1cam1 sh -c 'omxplayer --avdict rtsp_transport:tcp --win \"0 0 640 428\" rtsp://myvideo --live -n -1'";
    camera_feeds=('c1=(dis1cam1 dis1cam2 dis1cam3 dis1cam4 dis1cam5 dis1cam6 dis1cam8 dis1cam9)' 'c2=(dis2cam1 dis2cam2 dis2cam3 dis2cam4)')
    for elt in "${camera_feeds[@]}";do eval $elt;done

    # Start displaying camera feeds
    case "$1" in
    start)
    for i in "${$2[@]}"
    do
    eval eval '$'$i
    done
    echo "Camera Display 1 Started"
    ;;

Is there a way to pass the 2nd argument to call the c2 set ?

in this way is working perfect:

        #!/bin/bash
 dis1cam1="screen -dmS dis1cam1 sh -c 'omxplayer --avdict rtsp_transport:tcp --win \"0 0 640 428\" rtsp://myvideo --live -n -1'";

        camera_feeds=('c1=(dis1cam1 dis1cam2 dis1cam3 dis1cam4 dis1cam5 dis1cam6 dis1cam8 dis1cam9)' 'c2=(dis2cam1 dis2cam2 dis2cam3 dis2cam4)')
        for elt in "${camera_feeds[@]}";do eval $elt;done

        # Start displaying camera feeds
        case "$1" in
        start)
        for i in "${c1[@]}"
        do
        eval eval '$'$i
        done
        echo "Camera Display 1 Started"
        ;;
15
  • 2
    Why are you trying to use all the eval here? Commented Jun 27, 2017 at 11:51
  • Is to sanitize the multidimensional array and when i call "${c1[@]}" or "${c2[@]}" it will do the for loop, the eval is to start the service on omxplayer Commented Jun 27, 2017 at 11:53
  • Which exact version of bash is targeted? (4.3 provides a much better way of doing this). Commented Jun 27, 2017 at 11:53
  • @CharlesDuffy the Bash version is 4.3.30(1)-release Commented Jun 27, 2017 at 11:58
  • 1
    Good, then -- my answer should work. And you'll note there's no eval anywhere in it. Commented Jun 27, 2017 at 11:59

1 Answer 1

2

I would strongly advise implementing this differently.

#!/usr/bin/env bash

die() { echo "$*" >&2; exit 1; }
[[ $BASH_VERSION = [0-3]* ]] && die "Bash 4.3 or newer needed"
[[ $BASH_VERSION = 4.[0-2].* ]] && die "Bash 4.3 or newer needed"

dis1cam1() { : "code to start camera dis1cam1 here"; )
dis1cam2() { : "code to start camera dis1cam2 here"; )
# ...etc...

camera_feeds__c1=(dis1cam1 dis1cam2 dis1cam3 dis1cam4 dis1cam5 dis1cam6 dis1cam8 dis1cam9)
camera_feeds__c2=(dis2cam1 dis2cam2 dis2cam3 dis2cam4)

# here, we're showing the iterate-over-all-feeds case
# you can just set var=camera_feeds__c1 yourself if you prefer
for var in "${!camera_feeds__@}"; do  # var will be camera_feeds__c1 or camera_feeds__c2
  feed_name=${var#camera_feeds__}     # feed_name will be "c1" or "c2"
  declare -n camera_feeds=$var
  for i in "${camera_feeds[@]}"; do
    echo "Starting $i in feed $feed_name" >&2
    "$i" # look up and run code in variable named in $i
  done
  unset -n camera_feeds
done
  • "${camera_feeds__@}" expands to the list of shell variables whose names start with camera_feeds__; this is thus the name of our two arrays.
  • declare -n camera_feeds=$var then makes camera_feeds an alias for the array presently being iterated over, such that for i in "${camera_feeds[@]}" iterates over that array.
  • unset -n camera_feeds clears this association.
Sign up to request clarification or add additional context in comments.

9 Comments

No, is not good this way because i need to invoke wich one to start.
So? Then take the name from your argument list instead of from the results of iterating over the full set of variables. The technique of using namerefs is what's important here; if you use var="camera_feeds__$2" instead of a for loop, that makes little difference.
The idea with this script is to start a screen randomly or by command in argument, so first set of cams will stop and next will start, what you do is to start the entire set, and is not fine as i need to declare wich set to start.
Sure, but the technique I'm showing to iterate over an array named in a variable is completely separable from that. Take the part you want, discard the part you don't.
@ndAR, ...and the other thing -- and it's important -- is that your objections are all based on details you didn't include in the question, meaning that they aren't based on things that make the answer nonresponsive. It's not my problem that you asked a vague question that doesn't reflect what you actually want to do.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.