1

I'm using parameter substitution with an error message, such as ${var1:?'some message'}. I've incorporated a multi-line error message. Presently, it only functions properly when enclosed within single quotes, with line breaks inserted using the Enter key. Is there a clever way to allow acceptance of multiple lines, saved separately?

I'm just curious about exploring this. Please avoid suggesting alternative syntax involving if statements unless it's directly relevant.

Cases:

works: single quote

needed=${1:?'first error line
second error line
third error line'}

not working: call another string variable

usage_message='Please use this script by providing the following arguments:
1: <e.g user name>
2: <e.g run script>
3: <e.g something else>'

username=${1:?$usage_message} run_script_path=${2:?$usage_message} where_to_save=${3:?$usage_message}

not working: call a function

function get_message {
       echo -e "first line \nsecond line\nthird line"
       # or
       # printf "first line \nsecond line\nthird line"
}

needed=${1:? $(get_message)}

Other discussion about parameter substitution: https://stackoverflow.com/a/77772942/13413319

  • You need double quotes around the expansion of the multiline variable I think - username=${1:?"$usage_message"} – steeldriver Feb 20 '24 at 01:47
  • Wow, actually very simple. It works with both variable and the subshell call to the function. Thanks. You could re-post an answer to be marked as done. – programmer Erfan Feb 20 '24 at 01:53

1 Answers1

1

Although the POSIX standard for parameter expansion is not clear on the matter, and the RHS of an assignment is one of the few places in which bash parameter expansion does not undergo word splitting in general1, it appears that you need to double quote the multiline variable expansion to prevent word splitting2 in this context. So whereas

(unquoted)

$ username=${1:?$usage_message}
bash: 1: Please use this script by providing the following arguments: 1: <e.g user name> 2: <e.g run script> 3: <e.g something else>

(quoted)

$ username=${1:?"$usage_message"}
bash: 1: Please use this script by providing the following arguments:
1: <e.g user name>
2: <e.g run script>
3: <e.g something else>

See also When is double-quoting necessary?.


  1. for example

     $ var=foobar
     $ username=${var/bar/$usage_message}
     $ declare -p username
     declare -- username="fooPlease use this script by providing the following arguments:
     1: <e.g user name>
     2: <e.g run script>
     3: <e.g something else>"
    
  2. although apparently not globbing, for example

     $ word=*
     $ username=${1:?$word}
     bash: 1: *
    
steeldriver
  • 81,074
  • Quoting shouldn't be necessary here though. No other shell needs them. POSIX is not clear as to how the word should be expanded, but no reading of it would seem to allow that weird behaviour of bash where expansions are split on IFS (without globbing) and joined back with spaces. In zsh, the behaviour will change in the next version, but as it stands, newlines will be rendered as \n. – Stéphane Chazelas Feb 20 '24 at 06:28
  • (see also https://www.zsh.org/mla/workers/2024/msg00122.html for zsh) – Stéphane Chazelas Feb 20 '24 at 07:06
  • putting the quotes on the outside of the expansion ("${var?$msg}") also doesn't seem to help here. $'...' quotes seem to work, though: ${var?$'error\nmessage'} (with or without outer double quotes) – ilkkachu Feb 20 '24 at 09:22
  • Thanks @StéphaneChazelas - may I incorporate your comment into the answer? BTW is some additional flag or option necessary in zsh to enable the inner expansion? In zsh 5.8.1 I just seem to get the literal string $usage_message, despite man zshexpn indicating that "replacement text" is "subject to parameter expansion". – steeldriver Feb 20 '24 at 12:40
  • Sure. See https://www.zsh.org/mla/workers/2023/msg00036.html which the other message above replies to. – Stéphane Chazelas Feb 20 '24 at 13:09
  • @StéphaneChazelas thanks - I have (cowardly) avoided any mention of zsh for now - but made it a community wiki if you would like to expand on that – steeldriver Feb 20 '24 at 15:27