0

I want to write a small script of parsing all the comments of the C file using shell script but I am not even getting the read o/p correct,I am getting the file o/p mixed with other garbage data.

>/.1432804547.3007 /.1432804567.3007 /.1432804587.3007 /.1432804608.4021 /.1432804628.4021 /.1432804648.4021 /.1432804668.4021 /.1432804688.4021 /bin >/boot /dev /etc /home /lib /lib64 /lost+found /media /misc /mnt /net /opt /proc >/root /sbin /selinux /srv /sys /tmp /usr /var
>parsed_comments.tmp parse_func.sh file_update_time - update mtime and ctime time
>parsed_comments.tmp parse_func.sh @file: file accessed
>parsed_comments.tmp parse_func.sh
>parsed_comments.tmp parse_func.sh Update the mtime and ctime members of an inode and mark the inode
>parsed_comments.tmp parse_func.sh for writeback. Note that this function is meant exclusively for
>parsed_comments.tmp parse_func.sh usage in the file write path of filesystems, and filesystems may
>parsed_comments.tmp parse_func.sh choose to explicitly ignore update via this function with the
>parsed_comments.tmp parse_func.sh S_NOCMTIME inode flag, e.g. for network filesystem where these
>parsed_comments.tmp parse_func.sh timestamps are handled by the server.
>*/
>void file_update_time(struct file *file)

Here is what I am doing..

   parse_comments() {
    local filename="$1"
    while read line; do
    echo $line | grep "*"
    done < "$filename"
    parse_comments "/root/rpmbuild/linux-2.6.32-431.17.1.el6.x86_64/fs/inode.c"

I have tried all the solutions(like- while read -r, while read -u 3 and other too) told on SO for while read problem none of the solution worked for me. I don't know whats wrong with read with while loop please help... If I use 'awk' for the same work it works fine. But 'awk' doesn't serve my purpose.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Ashish Maurya
  • 131
  • 1
  • 4
  • 1
    If you was writing a program about selling eggs, would you use the *eggs* tag to ask about it? – Iharob Al Asimi Jun 04 '16 at 19:58
  • 3
    Run this through http://shellcheck.net/ and fix the bugs it reports before you start here. – Charles Duffy Jun 04 '16 at 19:59
  • 1
    I'm not sure what the first code block is supposed to represent. Is that the output, or what you tried to run, or the contents of the input file...? – trent Jun 04 '16 at 19:59
  • 1
    @trentcl, output is very believable. Every `/*` is going to be expanded into a list of files in the root filesystem, f'rinstance, due to the lack of quoting. – Charles Duffy Jun 04 '16 at 20:00
  • By the way -- one of the big problems here is that when using some piece of advice (like `read -r`) didn't work, the OP abandoned it entirely. Sometimes it takes more than one change to fix a piece of software. If you need both change-1 and change-2, but you only try them individually and throw them out if they don't do everything you want, you'll never get it right. – Charles Duffy Jun 04 '16 at 20:01
  • @erikced, that's a chunk of it, yes, but the `grep` is broken too; needs to be `[*]`, or `fgrep`, to be valid. – Charles Duffy Jun 04 '16 at 20:02
  • That said, the overall here approach here is insanely inefficient. Why invoke `grep` once per line, instead of just run grep a single time and loop over its output? – Charles Duffy Jun 04 '16 at 20:03
  • @CharlesDuffy Oh... I see. Without knowing what the input file looked like, I didn't know what was going on – trent Jun 04 '16 at 20:05
  • 1
    ...anyhow, as it is, this doesn't describe desired behavior (what the OP actually wants to accomplish -- why couldn't it just be `fgrep -e '*' inode.c`?), so it's failing to meet the criteria at http://stackoverflow.com/help/mcve – Charles Duffy Jun 04 '16 at 20:06
  • 1
    @CharlesDuffy : thanks I was not aware of shellcheck.net . It solved the problem. – Ashish Maurya Jun 05 '16 at 08:47
  • Thanks everyone specially @CharlesDuffy , The problem got solved..I missed very basic thing. shellcheck.net solved the problem. Here is modified code. `while read -r line; do echo "$line" | fgrep -e "*" done < "$filename"` – Ashish Maurya Jun 05 '16 at 08:56
  • Just `grep -F '*' "$filename"` is much simpler and efficient, and also handles binary files correctly if need be. – tripleee Jun 05 '16 at 11:25

1 Answers1

0

Problem got solved on shellcheck.net. Here is modified code...

parse_comments() {
    local filename="$1"
    while read -r line; do
    echo "$line" | fgrep -e "*" 
    done < "$filename"
}
parse_comments "/root/rpmbuild/linux-2.6.32-431.17.1.el6.x86_64/fs/inode.c"
Ashish Maurya
  • 131
  • 1
  • 4
  • Why do you have the `while read` loop at all, instead of just running `fgrep` once on the whole file? That is, it would be much more efficient to write `parse_comments() { fgrep -e '*' <"$1"; }` -- if you time it in practice, you'll see it runs noticeably quicker on large files than the current approach. – Charles Duffy Jun 05 '16 at 16:09
  • @CharlesDuffy : Actually this is just start of my work. I have to do lot of other things in while loop, this is why I am using it. But off course performance also is the key factor, I will work on your advice. Very thankful to you for advice. – Ashish Maurya Jun 05 '16 at 18:24
  • Even if you need to do other things with the result, calling `grep` one per line is still an inexcusable amount of overhead. You can use `[[ $line =~ '*' ]]` to check whether a line contains a literal asterisk more quickly, or you can replace `< "$filename"` with `< <(fgrep -e '*' "$filename")` to have the loop iterate over output from `grep` only. – Charles Duffy Jun 06 '16 at 14:14
  • @CharlesDuffy: Yes that replacement looks cool, Thanks for continuous advises. – Ashish Maurya Jun 09 '16 at 08:31