3

我处理压缩文件的脚本。我想做一个“直到循环”直到变量的内容与模式匹配。该脚本使用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' 开头的字符串。

图案好吗?

4

2 回答 2

5
$ 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

不要忘记<<<在你的表达式中,你不是在 grep 文件,而是一个字符串。为了更符合 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:\n\n$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 有用得多。

于 2013-05-02T15:24:35.400 回答
3

您不希望行中的反引号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]$'

对于正则表达式等内容,单引号通常比双引号更安全。


我只想检查part在 Zenity 输入对话框中写入的变量是否格式正确。我刚刚意识到grep需要一个文件,但我part是在这个脚本中初始化的一个变量。现在怎么相处?

bash中,您可以使用<<<运算符从字符串重定向:

until grep -E "$pattern" <<< "$part"

在大多数其他 shell 中,你会写:

until echo "$part" | grep -E "$pattern"

当然,这也适用于bash

于 2013-05-02T15:21:47.760 回答