1

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

sum=0;  
cnt=0

while read line
do

   case "$line" in

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

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

done

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!

3
  • Why don't you make [0-9]* ) as first condition, then make the second condition *) to catch all other thing.
    – cuonglm
    Commented 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
    Commented 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). Commented Mar 25, 2015 at 9:25

1 Answer 1

0

You can do...

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

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
done

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

b=${IFS%?}
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
done
11
  • 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. Commented Mar 25, 2015 at 4:39
  • @user3295764 - Oh, yeah, you really need the zeroes? Ok.
    – mikeserv
    Commented 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 Commented Mar 25, 2015 at 5:00
  • and integers that have just one space like ' 20' and '2 ' Commented 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
    Commented 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 .