我有以下 Bash 脚本,它捕获 TUI 数据(zenity)以准备数据库插入语句:
#!/bin/bash
INPUT=NULL,2,Van Tassel,NULL,5,6,,8
INPUT="$(echo $INPUT | ( IFS=, read a b c d e f g h ; echo "$a,${b}xxx,$c,$d,${e}xxx,${f}xxx,${g}}
xxx,${h}xxx" ))"
IFS=,; set -f; set -- $INPUT; out=
for i in "$@"; do
case "$i" in
"") echo empty input not allowed; exit 0;;
NULL) out="$out,$i";;
*xxx) out="$out,${i/%xxx/}";;
*) out="$out,\$\$$i\$\$";;
esac;
done
echo "${out:1}"
运行此脚本时我收到以下错误消息:
./err.txt: line 4: Tassel,NULL,5,6,,8: command not found
empty input not allowed
这个脚本有两个问题,我不知道如何解决。首先,只有输入“Van Tassel”或“VanTassel”时,Van Tassel 条目才会起作用,而这并不是从 TUI 界面接收多个字符串的方式。
第二个问题是“”)不起作用。如果我再次运行相同的脚本,但写入 VanTassel 而不是 Van Tassel,我会得到以下输出,而不是消息“不允许空输入”。
NULL,2,$$VanTassel$$,NULL,5,6,,8
事实不应该如此,因为第 7 个字段是空的。
有人可以帮忙吗?
答案1
INPUT=NULL,2,Van Tassel,NULL,5,6,,8
就像foo=bar baz
:在环境中使用变量运行baz
。foo
在bar
shell 脚本中,您需要引用或转义空格来抑制此行为。对于静态行,引用整个值通常是最好的解决方案:
INPUT='NULL,2,Van Tassel,NULL,5,6,,8'
在发布的代码中,该行是静态的,但实际上“从 TU 接口接收到多个字符串”,对吗?在这种情况下,解决方案可能取决于这种情况是如何发生的。
当你声称输出是时
NULL,2,$$VanTassel$$,NULL,5,6,,8
,它实际上是NULL,2,$$VanTassel$$,NULL,5,6,} ,8
因为在您的代码中有
${g}}
一个新队之后就好了。下次发布您正在测试的代码或测试您正在发布的代码。:)据称该案例
"")
不起作用,因为您xxx
首先注入了第 7 个字段!以这种方式修改的字段永远不会匹配空字符串;它将匹配*xxx
。然后您xxx
在构建时删除out
,字段将恢复为其原始空值。echo $INPUT
非常脆弱,可能会给你意想不到的结果。Unquoted 的$INPUT
行为类似于在这个答案中:发生拆分和文件名生成(通配)。请注意,当我们set -- $INPUT
稍后使用时,我们做想要拆分,我们抑制了通配符(set -f
早些时候)。但您的echo $INPUT
容易出现这两种情况。即使您使用echo "$INPUT"
,这仍然适用:为什么printf
比 更好echo
?在 Bash 中你可以IFS=, read … <<<"$INPUT"
使用,
read -r
除非你知道你不想要-r
(参见help read
)。或许
INPUT
应该是input
。阅读此文:shell 脚本中变量的命名约定。