如何在bash中使用grep字符串直到循环?

时间:2013-05-02 15:12:30

标签: bash loops grep zenity

我在编写压缩文件的脚本。我想做一个'until loop'直到'变量的内容与模式匹配。该脚本使用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'开头的字符串。

模式是否正常?

2 个答案:

答案 0 :(得分: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更有用。

答案 1 :(得分: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]$'

单引号通常比正则表达式之类的双引号更安全。


  

我只是想在Zenity条目对话框中写完后,检查名为part的变量是否格式正确。我刚刚意识到grep需要一个文件,但我的part是在这个脚本中初始化的变量。如何相处?

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

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

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

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

当然,这也适用于bash