How to grep a string in until loop in bash?

12,317

Solution 1

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

Solution 2

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.

Share:
12,317
Nojas
Author by

Nojas

Updated on June 04, 2022

Comments

  • Nojas
    Nojas almost 2 years

    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?

  • Nojas
    Nojas about 11 years
    Thanks.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?
  • Nojas
    Nojas about 11 years
    Thank you. I must use zenity (it iss project's directive). I have a problem with pattern. I want it to accept what was said above and '0' (if there's no division).
  • michaelmeyer
    michaelmeyer about 11 years
    @Nojas: I guess you want this: grep -E '(^0$|^[1-9][0-9]*[km]$)'
  • Nojas
    Nojas about 11 years
    It doesn't work neither for 0 nor for the rest of the pattern.