0

I have this code which calls dialog with parameters and should create a menu with a single entry:

!/bin/bash
   
menu() {
        echo dialog --clear --stdout --title "Menu" --menu "menu" 0 0 0 $1  # dialog --clear --stdout --title Menu --menu menu 0 0 0 1 "my menu item" 1
        dialog --clear --stdout --title "Menu" --menu "menu" 0 0 0 $1 
}

echo $(menu "1 \"my menu item\"")

It does create the menu but it creates 2 menu entries instead of one and adds double quotes to the menu item.

enter image description here


If I use this code it works:

!/bin/bash
   
echo dialog --clear --stdout --title "Menu" --menu "menu" 0 0 0 1 "my menu item"  # dialog --clear --stdout --title Menu --menu menu 0 0 0 1 my menu item
dialog --clear --stdout --title "Menu" --menu "menu" 0 0 0 1 "my menu item"

enter image description here

As can be seen, even though in the first case the menu item parameter is in double quotes (see echo) it's interpreted as 3 parameters.

How can I make the first example work as expected?

1
  • 6
    Based on this and your previous question, I think you're not entirely clear about the difference between literal and syntactical quotes. mywiki.wooledge.org/Quotes is a good read to get you started. Commented Nov 8, 2020 at 22:49

2 Answers 2

2

Why does passing a quoted string to Bash function and using as command parameter doesn't work as expected?

I don't think it is argument passing that works differently than you expect, but rather command-line expansion, and especially parameter expansion. Let's take a more demonstrative example:

analyze2() {
  echo -n "  $# words: "
  for word; do
    echo -n " $word"
  done
  echo
}

analyze() {
  echo arg count: $#
  for arg; do
    echo $arg
    analyze2 $arg
    analyze2 "$arg"
  done
}

Now call it:

$ analyze foo "bar baz" "\"African or European swallow?\""
arg count: 3
foo
  1 words:  foo
  1 words:  foo
bar baz
  2 words:  bar baz
  1 words:  bar baz
"African or European swallow?"
  4 words:  "African or European swallow?"
  1 words:  "African or European swallow?"

Among the key points to take away is that there is a difference between quotes that appear literally in a command and those that result from parameter expansion. Only the former have any syntactic relevance, preventing word splitting and being subject to quote removal. Quotes resulting from parameter expansion are just data.

How can I make the first example work as expected?

If you want your menu function to pass two arguments on to dialog, then pass two arguments to it. Inside the function, you can pass on the full argument list by using one of the special parameters $* and $@. These differ in the effect of expanding them inside double quotes: "$*" expands to all the arguments as one shell word, whereas "$@" expands to a separate shell word for each argument.

!/bin/bash
   
menu() {
        echo dialog --clear --stdout --title "Menu" --menu "menu" 0 0 0 "$@"  # dialog --clear --stdout --title Menu --menu menu 0 0 0 1 "my menu item" 1
        dialog --clear --stdout --title "Menu" --menu "menu" 0 0 0 "$@" 
}

echo $(menu 1 "my menu item")
Sign up to request clarification or add additional context in comments.

Comments

2

Try something like:

#!/usr/bin/env bash

menu() {
  dialog \
    --clear \
    --stdout \
    --title "Menu" \
    --menu "menu" 0 0 0 \
    "$@" 
}

choice=$(
  menu \
    1 'my menu item' \
    2 'my other menu item'
)

if [ -n "$choice" ]; then
  printf 'Choice is %s\n.' "$choice"
else
  echo 'Cancelled!'
fi

2 Comments

But this doesn't work if I need to pass multiple parameters to the function! I mean if I have something like this: ``` menu() { dialog \ --clear \ --stdout \ --title $1\ --menu "menu" 0 0 0 \ "$@" \ $3 } ```
@user5507535 "$@" is already passing all the parameters (arguments) to the function.

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.