0

Problem Description

Given a plaintext file args.in containing one line of command line arguments, read them into an array.

Problem Formulation

We have 4 files:


args.in:

"ab" c

refimpl.sh:

read -r line
bash -c "bash showargs.sh $line"

arrayimpl.sh:

arr=()

# BEGIN-------------------------
# Input comes from stdin.
# You need to set arr here.
# END---------------------------

echo "${#arr[@]}"
for i in "${arr[@]}"; do
    echo "$i"
done

showargs.sh:

echo "$#"
for i in "$@"; do
    echo "$i"
done

Put them into the same folder. We want you to implement arrayimpl.sh so that

bash refimpl.sh < args.in

and

bash arrayimpl.sh < args.in

give the same output.

Your solution should only contain a single file arrayimpl.sh.

Output Example

2
ab
c

This problem is a better formulation of this but not a dup of this. Some solutions work there but not here. For example, when we have the following input:

args.in:

"a\"b" c

There is no known solution yet.

Community
  • 1
  • 1
Cyker
  • 9,946
  • 8
  • 65
  • 93
  • @sorontar I want the scripts to read from stdin. So they are called like `./refimpl.sh < args.in`. That part has been fixed. – Cyker Dec 26 '16 at 00:11
  • @StevenPenny Adding shebang here makes the question even longer. I think either way doesn't affect the result. – Cyker Dec 26 '16 at 00:14
  • 1
    If input comes on the form like `"a b" c` on stdin, you can do `eval "arr=( $(cat) )"`. – that other guy Dec 26 '16 at 00:15
  • @thatotherguy Why don't you write an answer then? I tested with several inputs and it looks good. The only concern I have is about the potential risk of `eval` which is very difficult to harness. – Cyker Dec 26 '16 at 01:30
  • There's is no risk or problem with using `eval` that `refimpl.sh` doesn't already have. – that other guy Dec 26 '16 at 02:14
  • @Cyker Make the file `echo '"ab" c "d e" f\g *' > args.in` and try `eval "arr=( $(cat) )"` again. Thats an example of incorrect backslash quote removal and filename expansion. Just to name two problems. –  Dec 26 '16 at 02:19
  • @cyker, and to show how insecure, make args.in like this: `echo '"ab" c "d e" f\g * $(date)' > args.in` and either try `eval "arr=( $(cat) )"` or your `bash -c` idea. In short: **don't do that**. –  Dec 26 '16 at 02:23
  • @cyker Evan a quoted $(date) will execute: `echo '"$(date)"' > args.in; echo $( ' "${arr[@]}"`. –  Dec 26 '16 at 02:27

1 Answers1

2

The expected solution for this assignment is something equivalent to:

eval "arr=( $(cat) )"

This evaluates input as shell words, which is what refimpl.sh also does.

This is for toy problems and homework assignments only. Real software should not use executable code as a data format.

that other guy
  • 116,971
  • 11
  • 170
  • 194