I have a program that is currently working, but I need to modify it to ignore some stdin that is not fitting for its correct function.

Right now, to run the program: printf "1\n3\n5\n" | sh prog

The program currently ignores non-integer input (like floats), but I also need it to ignore something like '4 10' on the same line and '5 text' etc.

#! /bin/sh


while read line

   case "$line" in

        *[.]*  )   #------I think here is where the regex needs to be edited
            printf "\n0"

        [0-9]* )
            sum=`expr "$sum" + "$line"`
           cnt=`expr "$cnt" + 1`
            printf "\n%s" `expr $sum / $cnt`


I'm pretty sure it's just a matter of changing the regex on the line I pointed out so that it goes to the print 0 and continue case with the two non-desired input types I described above but I am having trouble with it.

Thank you!

  • Why don't you make [0-9]* ) as first condition, then make the second condition *) to catch all other thing.
    – cuonglm
    Mar 25, 2015 at 3:33
  • Shell case patterns are not regular expressions; they are more like shell globs. The pattern *[.]* means anything or nothing followed by a single character followed by anything or nothing. I'm pretty sure that' not what you intended.
    – msw
    Mar 25, 2015 at 3:33
  • if you're using GNU Bash, you can get regex matching with [[ $foo ~= pattern ]] (see the man page). With shopt -s extglob, you can use things like foo.@(zip|7z) in glob expressions. (also ?, *, +, and ! operators). Mar 25, 2015 at 9:25

1 Answer 1


You can do...

while read line
do    line=${line%%[!0-9]*}
      [ -n "$line" ] || continue
      : work w/ digits at line's head

Alternatively - and probably faster - you can do:

tr -cs 0-9\\n \ |
while IFS=\  read num na
do    ${num:+":"} continue
      : work w/ first seq of digits on line

Or is if you want to ignore completely any line containing anything but spaces, tabs, or numbers, or even any line containing two space-separated nums...

grep "^[$b]*[0-9]\{1,\}[$b]*$" |
while read num; do : stuff with "$num"; done

With case you could do it like this:

while read num
do    case ${num:--} in 
      *[!0-9]*) continue;;esac
      : something w/ $num
  • I implemented the last version of your solution to my code and the problem is that it only prints a zero in the place of an incorrect input once, not for each case. Mar 25, 2015 at 4:39
  • @user3295764 - Oh, yeah, you really need the zeroes? Ok.
    – mikeserv
    Mar 25, 2015 at 4:52
  • 1
    Actually, I figured out adding printf statements, but the bigger issue is that it should support negative numbers Mar 25, 2015 at 5:00
  • and integers that have just one space like ' 20' and '2 ' Mar 25, 2015 at 5:00
  • @user329574 - ok, we can do that, but in that case can I use grep or sed - they're bound to be way faster than a shell while read; case ... in loop - that's slow, man. About the blanks though - there won't be any of those - because the shell's $IFS eats them at head and tail of line.
    – mikeserv
    Mar 25, 2015 at 5:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .