Question

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:

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'.

Is the pattern ok?

Was it helpful?

Solution

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

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.

OTHER TIPS

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

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

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

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 part is well-formed after writing it in Zenity entry dialog. I just realised that grep needs a file, but my part is a variable initialised in this script. How to get along now?

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

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

In most other shells, you'd write:

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

This also works in bash, of course.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top