How about using bash's builtin 'read' function with the period character as delimiter to read each whole sentence into a variable, and then capitalizing the initial character of the variable? Something like
$ cat myfile
i am andrew. you
are jhon. here we are
forever.
$ while read -rd\. sntc; do printf "%s. " "${sntc^}"; done < myfile; printf "\n"
I am andrew. You
are jhon. Here we are
forever.
To handle multiple sentence terminators e.g. ? and ! as well as the regular period, here is a different approach using 'awk' - note that the RT variable that allows us to recover the particular record terminator which matched a particular sentence is an extension that may not be available in all varieties of 'awk'
$ cat myfile
i am andrew? you
are jhon. here we are
forever!
$ awk 'BEGIN{RS="[.!?]+[ \t\n]*"}; {sub(".", substr(toupper($0), 1,1), $0); printf ("%s%s", $0, RT)}' myfile
I am andrew? You
are jhon. Here we are
forever!
Note that the record separator regex above will handle multiple consecutive delimiters ('!?!!!') and optional trailing spaces - which the read-based version doesn't.
As a further enhancement, let's try to add rudimentary handling of quoted sentences by modifying the RS regex once more and changing the sub so that it upper-cases the first non-quote character:
awk 'BEGIN{RS="[.!?]+[\"'\'']?[ \t\n]*"}; {match($0, "[^\"'\'']"); sub("[^\"'\'']", substr(toupper($0),RSTART,1), $0); printf ("%s%s", $0, RT)}'
e.g.
$ cat myfile
i am andrew. "are
you jhon?" 'here we are
forever!?'
$ awk 'BEGIN{RS="[.!?]+[\"'\'']?[ \t\n]*"}; {match($0, "[^\"'\'']"); sub("[^\"'\'']", substr(toupper($0),RSTART,1), $0); printf ("%s%s", $0, RT)}' myfile
I am andrew. "Are
you jhon?" 'Here we are
forever!?'
vim
, would an answer that works within vim, rather than a shell script, be useful?