我正在尝试使用由 4 个条目组成的表单创建一个由四个元素组成的数组:
new_prop=($(zenity --forms --title="my-script" --text="Insert the values" --separator=" " \
--add-entry="Name" \
--add-entry="Surname" \
--add-entry="Gender" \
--add-entry="Age"))
一般来说,用户可以将该Gender
字段留空,但其他 3 个字段必须填写。
问题是zenity
(我不知道yad
)如果条目留空,则不会创建空元素,而只是跳过该元素。例如,如果我插入Name
and Age
,zenity
则生成一个包含 2 个元素的数组new_prop
。
如何检查表单中的条目是否为空?表单是否用zenity
或制作并不重要yad
。
谢谢你!
答案1
问题是,如果条目留空,zenity(我不知道yad)不会创建空元素,而只是跳过该元素。例如,如果我插入姓名和年龄,zenity 会生成一个包含 2 个元素的数组 new_prop。
如果条目留空,它确实会创建一个空元素,只是您在 shell 中使用 split+glob 运算符和空格分隔符来分割其输出。
空格是一种空白字符,因此,当在 中 找到时$IFS
(默认情况下如此),对于分割部分,前导和尾随字符将被忽略,并且一个或多个 IFS 空白的序列被视为一个。当然,要求通配符是没有意义的。
使用(假设 bash 4.4 或更高版本能够使用wait "$!"
getzenity
的退出状态):
readarray -t new_prop < <(
zenity --forms \
--title="my-script" \
--text="Insert the values" \
--separator=$'\n' \
--add-entry={Name,Surname,Gender,Age}
) && wait "$!"
(假设值不能包含换行符)
要使用 split+glob,您需要使用非空格的分隔符(在最近的 bash 版本中,在区域设置中分类为单字节字符,仅在旧版本中包含空格、制表符、换行符),当然还要禁用 glob你不想要的部分。
由于zenity
使用分隔符,情况变得更加复杂,而 bash 中的 IFS 分割需要分隔符,并且命令替换会去除尾随换行符。
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
在 bash 的 IFS 分割的最后一行末尾添加一个 RS,以查看相应的字段,即使它是空的。这还可以防止最后一个字段中的尾随换行符被命令替换删除。
现在,字段中的换行符不再是问题,但 RS 字符却是问题。
在 中zsh
,您可以使用任意分隔符(不仅仅是单个字符)及其s
参数扩展标志:
sep=$'\36@@%%@@\36'
new_prop=(
"${(@ps[$sep])$(
zenity --forms \
--title="my-script" \
--text="Insert the values" \
--separator=$sep \
--add-entry={Name,Surname,Gender,Age})}"
)
(尽管由于命令替换,这仍然会删除最后一个字段中的尾随换行符(如果有))。
1 在我的测试中,zenity
如果您复制粘贴换行符或使用其他输入方法(例如在某些系统上通过 Unicode 代码点输入字符的Ctrl++ Shift) ,则允许您嵌入换行符。它们在 GUI 中呈现为 ⏎,但在 stdout 上输出为换行符ua