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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16341609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:19:47  来源:igfitidea点击:

How to grep a string in until loop in bash?

bashloopsgrepzenity

提问by Nojas

I work on a script compressing files. I want to do an 'until loop' til' the content of variable matches the pattern. The script is using zenity. This is the major part:

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

I want it to accept string containing digits ended with 'k' or 'm' (but not both of them) and don't accept string started with '0'.

我希望它接受包含以 'k' 或 'm' 结尾的数字的字符串(但不是两者),并且不接受以 '0' 开头的字符串。

Is the pattern ok?

图案好吗?

回答by michaelmeyer

$ 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

Don't forget the <<<in your expression, you're not grep'ing a file, but a string. To be more POSIX-compliant, you can also use:

不要忘记<<<表达式中的 ,您不是在搜索文件,而是字符串。为了更符合 POSIX,您还可以使用:

echo 1023m | grep -w '^[1-9][0-9]*[km]$'

But it is kinda ugly.

但它有点丑。

Edit:

编辑

Longer example:

更长的例子:

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

Also, this is not directly related to the question, but you may want to have a look at Yad, which does basically the same things Zenity does, but has more options. I used it a lot when I had to write Bash scripts, and found it much more useful than Zenity.

此外,这与问题没有直接关系,但您可能想看看Yad,它与 Zenity 所做的事情基本相同,但有更多选择。我在编写 Bash 脚本时经常使用它,发现它比 Zenity 有用得多。

回答by Jonathan Leffler

You don't want the back-quotes in the untilline. You might write:

您不希望该行中出现反引号until。你可能会写:

until grep -E "$pattern" "$part"
do
    ...body of loop...
done

Or you might add arguments to grepto suppress the output (or send the output to /dev/null). As written, the script tries to execute the output of the grepcommand and use the success/failure status of that (not the grepper se) as an indication of whether to continue the loop or not.

或者您可以添加参数以grep抑制输出(或将输出发送到/dev/null)。正如所写,脚本尝试执行grep命令的输出并使用它的成功/失败状态(而不是grep本身)作为是否继续循环的指示。

Additionally, your pattern needs some work. It is:

此外,您的模式需要一些工作。这是:

pattern="^([0-9]{1}[0-9]*([km])$"

There is an unmatched open parenthesis in there. It also looks to me as though it is trying to allow a leading zero. You probably want:

那里有一个无与伦比的开括号。在我看来,它也好像试图允许前导零。你可能想要:

pattern='^[1-9][0-9]*[km]$'

Single quotes are generally safer than double quotes for things like regular expressions.

对于正则表达式之类的东西,单引号通常比双引号更安全。



I just want to check if my variable called partis well-formed after writing it in Zenity entry dialog. I just realised that grepneeds a file, but my partis a variable initialised in this script. How to get along now?

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

In bash, you can use the <<<operator to redirect from a string:

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

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

In most other shells, you'd write:

在大多数其他 shell 中,您会这样写:

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

This also works in bash, of course.

bash当然,这也适用于。