Skip to main content

Timeline for Handling long-options with getopts

Current License: CC BY-SA 4.0

15 events
when toggle format what by license comment
Oct 31, 2021 at 11:51 comment added ilkkachu And yes, the single quotes and spaces are what the extra eval would mess up
Oct 31, 2021 at 11:49 comment added ilkkachu And of course in general we could use eval in something like eval "$(date +"hour=%H min=%M sec=%S")" which would ask date to print a string that looks like hour=13 min=39 sec=55, which we'd then know would be useful as a command to the shell if we want those values assigned to the three variables. But we wouldn't use eval "$(date +"%H:%M:%S")" because the output 13:39:55 wouldn't be useful as a command. So we just do time="$(date +"%H:%M:%S")" instead. The point is that we'd only use eval if the output is designed to look like a command line, like one we'd write on the prompt.
Oct 31, 2021 at 11:35 comment added ilkkachu But getopt explicitly does an array->string conversion, just for the purpose of it being converted back to an array, and only because it's not possible to directly return an array from a command substitution. (The output of a command is a stream of bytes, so just a single string, no structure inherently. That structure needs to be built with delimiter characters, e.g. the colons in /etc/passwd delimiting the fields. Just those aren't general, you can't have a colon in a value if the colon is the delimiter. Shell quoting is general and easily available with eval for use with getopt)
Oct 31, 2021 at 11:31 comment added ilkkachu @khin, one way to look at it, is that a shell command is a single string, while what results from it after quote processing is conceptually an array (or list, if you will). The command ls 'foo bar' blah gets converted to the array (ls, foo bar, blah). What the user initially gives as command, e.g. getopts_test ... is a string, but even before the function runs, that gets converted to an array. The elements of that array being ($1, $2, ...) inside the function. Then, you already have an array, and there's no need for the string->array conversion any more.
Oct 31, 2021 at 5:28 comment added Vera You are correct. Using getopts_test -f -g 130 --colour="170 20" "foo'bar" yields bash: unexpected EOF while looking for matching '. bash: syntax error: unexpected end of file when using eval set -- "${aggr[@]}". Whereas the problem does not occur with set -- "${aggr[@]}".
Oct 31, 2021 at 5:08 comment added Vera I agree that users would not want to use getopts_test "'foo bar'". They would want to run the command with getopts_test "foo bar". This directs me to use set -- "${aggr[@]}". When users pass getopts_test -f -g 130 --colour="170 20" "foo bar" * and one of the files has spaces (e.g. "un tit.pdf"), using eval, does split "un" from "tit.pdf". I can see that using eval is not the right way to parse arguments when the developer decides to handle user arguments directly without using getopts or getopt. Are we agreed on these points @ilkkachu ?
Oct 31, 2021 at 4:50 comment added Vera Would you be so kind to explain what commands would be explicitly shell command? Am getting baffled with the terminology. Could there also be some tangible code examples?
Oct 31, 2021 at 4:39 comment added Vera For my getopts_test, it like that using an array is a neat idea. What do you think? Customarily, I pass filename as non-option arguments by using the break command.
Oct 30, 2021 at 17:18 comment added ilkkachu @khin, if you have something that's explicitly made to be a shell command, then you use eval. If not, then you don't. Your users probably don't want to enter args with spaces as getopts_test "'foo bar'", instead of the normal getopts_test "foo bar", and they'll probably also expect getopts_test * to work, even if some of the filenames contain whitespace (or shell special characters).
Oct 30, 2021 at 17:09 history edited ilkkachu CC BY-SA 4.0
added 281 characters in body
Oct 30, 2021 at 13:43 comment added Vera The biggest question is whether to use eval or not, because for the case of getopt, the use of eval seems necessary.
Oct 30, 2021 at 13:30 comment added Vera The code is intended ta address the portability problem. Have used getopt before.
Oct 30, 2021 at 11:01 comment added Vera Yes, I change each --context to -C.
Oct 30, 2021 at 11:01 history edited ilkkachu CC BY-SA 4.0
added 1 character in body
Oct 30, 2021 at 10:53 history answered ilkkachu CC BY-SA 4.0