How to grep a string in until loop in bash?
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 thatgrep
needs a file, but mypart
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.
Nojas
Updated on June 04, 2022Comments
-
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 about 11 yearsThanks.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 about 11 yearsThank 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 about 11 years@Nojas: I guess you want this:
grep -E '(^0$|^[1-9][0-9]*[km]$)'
-
Nojas about 11 yearsIt doesn't work neither for 0 nor for the rest of the pattern.