1

I'm trying to create an array of four elements using a form consisting of 4 entries:

new_prop=($(zenity --forms --title="my-script" --text="Insert the values" --separator=" " \
                        --add-entry="Name" \
                        --add-entry="Surname" \
                        --add-entry="Gender" \
                        --add-entry="Age"))

In general, the user can leave the Gender field empty, but the other 3 must be filled.

The problem is that zenity (I don't know yad) doesn't create an empty element if an entry is left empty, but simply it skips that element. For example, if I insert Name and Age, zenity makes an array new_prop of 2 elements.

How can I check if an entry in the form is left empty? It doesn't matter if the form is made with zenity or yad.

Thank you!

1 Answers1

2

The problem is that zenity (I don't know yad) doesn't create an empty element if an entry is left empty, but simply it skips that element. For example, if I insert Name and Age, zenity makes an array new_prop of 2 elements.

It does create an empty element if an entry is left empty, it's just that you used the split+glob operator with a whitespace separator in the shell to split its output.

Space is a whitespace character and as such, when found in $IFS (as it is by default), for the split part, leading and trailing ones are ignored and sequences of one or more IFS-whitespace are considered as one. And of course asking for globbing doesn't make sense.

Use (assuming bash 4.4 or newer to be able to use wait "$!" to get zenity's exit status):

readarray -t new_prop < <(
  zenity --forms \
         --title="my-script" \
         --text="Insert the values" \
         --separator=$'\n' \
         --add-entry={Name,Surname,Gender,Age}
) && wait "$!"

(assuming the values cannot contain newline characters¹)

To use split+glob, you'd need to use a separator that is not whitespace (single-byte characters classified as such in the locale in recent bash versions, space, tab, newline only in older versions) and of course disable the glob part which you don't want.

It's further complicated here by the fact that zenity uses a separator, while IFS-splitting in bash expects delimiters and command substitution strips trailing newline characters.

IFS=$'\36' # or any non-whitespace character not expected in the values
           # here using ASCII RS (record separator) character.
set -o noglob
new_prop=(
  $(
    set -o pipefail
    zenity --forms \
           --title="my-script" \
           --text="Insert the values" \
           --separator="$IFS" \
           --add-entry={Name,Surname,Gender,Age} |
      sed "\$s/\$/$IFS/"
  )
)

sed adds a RS at the end of the last line for bash's IFS-splitting to see a corresponding field even if it's empty. That also prevents trailing newlines in the last field from being removed by the command substitution.

Now, newlines in fields are no longer a problem but RS characters are.

In zsh, you'd be able to use arbitrary separators (not just single characters) with its s parameter expansion flag:

sep=$'\36@@%%@@\36'
new_prop=(
  "${(@ps[$sep])$(
    zenity --forms \
           --title="my-script" \
           --text="Insert the values" \
           --separator=$sep \
           --add-entry={Name,Surname,Gender,Age})}"
)

(though that still removes trailing newline characters if any from the last field because of command substitution).


¹ in my tests, zenity allows you to embed newline characters if you copy-paste them or use other input methods like the Ctrl + Shift + u, a found on some systems to enter characters via their Unicode codepoint. They're rendered as ⏎ in the GUI, but output as a newline character on stdout

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • Unfortunately, I have `bash` 4.2. Maybe I could check for the number of element of `new_prop` if the window is closed. However, removing `&& wait "$!"` since I'm on `bash` 4.2, leads to a `Stale file handle` message. How can I solve? Thank you – user9952796 May 04 '23 at 09:39
  • 1
    @user9952796, see edit. – Stéphane Chazelas May 04 '23 at 09:52