0

I have two lists of strings (with whitespace in each string), and want to read them one by one. The length of the strings are the same, so I get the length of one of them, via "${!argument[@]}", and try to read the elements of the lists. But it fails:

arguments="--a 100 --b 200" "--a 100 --b 200 --c"
settings="without_c" "with_c"
for index in "${!argument[@]}"
do
        setting=${setting[$index]}
        argument=${argument[$index]}
done

Gives the following error:

alp@ubuntu:~$ sh toy.sh 
toy.sh: 1: toy.sh: --a 100 --b 200 --c: not found
toy.sh: 2: toy.sh: with_c: not found
toy.sh: 3: toy.sh: Bad substitution
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
user3639557
  • 4,791
  • 6
  • 30
  • 55
  • Nope. that is in bash. – user3639557 Jun 22 '18 at 11:36
  • 1
    Do you not want to use bash? It's quite difficult to do this without arrays in plain sh. – John Kugelman Jun 22 '18 at 11:39
  • IMHO, that is irrelevant. This is a question with shell in its title and as its tag. I don't see a reason for it to be marked as duplicate. – user3639557 Jun 22 '18 at 11:42
  • 1
    Limiting answers to plain sh should be mentioned in your question, and it's also a good idea to explain why you have such a limitation. Bash is the de facto standard shell these days. Many people say "shell" and mean "bash", so it's worth being explicit that you don't. I don't mean to be argumentative, just trying to help you get good answers. – John Kugelman Jun 22 '18 at 11:48
  • 3
    See [Arrays in UNIX shell?](https://stackoverflow.com/questions/1878882/arrays-in-unix-shell) for bash solutions. – John Kugelman Jun 22 '18 at 11:50
  • POSIX sh doesn't have arrays at all. `"${!argument[@]}"` isn't valid syntax there, nor is `${setting[$index]}`. Why would you try to use it? (To make this bash, by contrast, you just need to fix your assignments: `arguments=( "--a 1000 --b 200" "--a 100 --b 200 --c" )`) – Charles Duffy Jun 22 '18 at 16:00
  • @user3639557, could you explain *why and how* this is not a duplicate of the previously-linked question, rather than simply stating a conclusion and assuming that this conclusion is self-evident to all other readers? – Charles Duffy Jun 22 '18 at 16:03

2 Answers2

1

Your first line reads

arguments="--a 100 --b 200" "--a 100 --b 200 --c"

This is a special case of the following structure:

V=X P

(with V being arguments, X being "--a 100 --b 200" and P being --a 100 --b 200 --c).

The semantic of such a statement is to execute the program P in an environment, where the environment variable V is set to X.

In your case, it means that you ask the shell to execute the "program" --a 100 --b 200 --c and such a program does not exist. This is what the error message says.

In your title, you say that you want to process a list, but you are using a programming language (Posix shell), which does not support lists. You are not using bash, as you claim in your comment, because if you would use bash, the error message would be different.

Of course, even in bash, the first line would be incorrect, because an array assignment (what you call a list is called an array in bash) in bash would follow the syntax name=(val1 val2 ....).

user1934428
  • 19,864
  • 7
  • 42
  • 87
0

I like to do "mock" 2 dimensional arrays in POSIX sh (/bin/sh) using something like the following. Note, you'll need to pick a delimiter (in this case |) that is not used in your strings.

#!/bin/sh
## Save this script as testloop.sh
for STRING in "red|little corvette" "green|hip, funky onions" "blue|high, high moon"
do
    IFS='|' read -r COLOUR THING <<-_EOF_

$STRING
_EOF_

    echo "The colour of the $THING is $COLOUR"
done

When you run that, you get:

sh testloop.sh
The colour of the little corvette is red
The colour of the hip, funky onions is green
The colour of the high, high moon is blue

For your example, you would use something similar

#!/bin/sh
## Save this script as loopArguments.sh

for STRING in "--a 100 --b 200|without_c|1st" "--a 100 --b 200 --c|with_c|2nd" "--a 300 --b 400|without_c|3rd"
do

    IFS='|' read -r LINE CSTATE NUMBER <<-_EOF_
$STRING
_EOF_

    echo "The $NUMBER line is $LINE and it is $CSTATE"
done

which will do this:

sh loopArguments.sh
The 1st line is --a 100 --b 200 and it is without_c
The 2nd line is --a 100 --b 200 --c and it is with_c
The 3rd line is --a 300 --b 400 and it is without_c
Silas Palmer
  • 2,687
  • 1
  • 29
  • 30