我正在编写一个压缩文件的脚本。我想做一个"直到循环",直到变量的内容与模式匹配。脚本正在使用zenity。这是主要部分:
part="0"
pattern="^([0-9]{1}[0-9]*([km])$"
until `grep -E "$pattern" "$part"` ; do
part=$(zenity --entry
--title="Zip the file"
--text "Choose the size of divided parts:
(0 = no division, *m = *mb, *k = *kb)"
--entry-text "0");
if grep -E "$pattern" "$part" ; then
zenity --warning --text "Wrong text entry, try again." --no-cancel;
fi
done
我希望它接受包含以"k"或"m"结尾的数字(但不能同时包含这两个数字(的字符串,而不接受以"0"开头的字符串。
图案可以吗?
$ grep -w '^[1-9][0-9]*[km]$' <<< 45k
45k
$ grep -w '^[1-9][0-9]*[km]$' <<< 001023m
$ grep -w '^[1-9][0-9]*[km]$' <<< 1023m
1023m
不要忘记表达式中的<<<
,您不是在输入文件,而是在输入字符串。为了更符合POSIX,您还可以使用:
echo 1023m | grep -w '^[1-9][0-9]*[km]$'
但它有点难看。
编辑:
更长的例子:
initmessage="Choose the size of divided parts:n(0 = no division, *m = *mb, *k = *kb)"
errmessage="Wrong input. Please re-read carefully the following:nn$initmessage"
message="$initmessage"
while true ; do
part=$(zenity --entry
--title="Zip the file"
--text "$message")
if grep -qw '^[1-9][0-9]*[km]$' <<< "$part" ; then
zenity --info --text 'Thank you !'
break
else
message="$errmessage"
fi
done
此外,这与这个问题没有直接关系,但你可能想看看Yad,它做的事情基本上与Zenity相同,但有更多的选择。当我必须编写Bash脚本时,我经常使用它,发现它比Zenity有用得多。
您不希望在until
行中使用反引号。你可以写:
until grep -E "$pattern" "$part"
do
...body of loop...
done
或者,您可以向grep
添加参数以抑制输出(或将输出发送到/dev/null
(。正如所写的,脚本尝试执行grep
命令的输出,并使用该命令的成功/失败状态(而不是grep
本身(作为是否继续循环的指示。
此外,您的模式还需要一些工作。它是:
pattern="^([0-9]{1}[0-9]*([km])$"
那里有一个不匹配的左括号。在我看来,它似乎也在试图让零领先。你可能想要:
pattern='^[1-9][0-9]*[km]$'
对于正则表达式之类的东西,单引号通常比双引号更安全。
我只想在Zenity条目对话框中写入名为
part
的变量后,检查它的格式是否正确。我刚刚意识到grep
需要一个文件,但我的part
是在这个脚本中初始化的一个变量。现在如何相处?
在bash
中,可以使用<<<
运算符从字符串进行重定向:
until grep -E "$pattern" <<< "$part"
在大多数其他shell中,你会写:
until echo "$part" | grep -E "$pattern"
当然,这也适用于bash
。