LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (http://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash- grep and loops (http://www.linuxquestions.org/questions/linux-newbie-8/bash-grep-and-loops-4175429419/)

calvarado777 09-28-2012 06:59 AM

Bash- grep and loops
 
Hello all, I am in week two of learning Bash and I am lost!
My first task is to search the current directory for files with the extensions .c and .cc, and search for the strings printf and fprintf within those files. IF the print statements are found, then I am to add in a header if it's not already there.

This is where I am at so far-- I am finding the man pages hard to understand and googling everything has become overwhelming!

Can anyone maybe just give me a few hints? My errors that I have run into so far is that I can't seem to get the right syntax when I am piping my 'ls' results to my grep in the outer for loop...so I eventually decided to work from the inside out...but now I can't seem to get the right type of arguements for my inner grep :-(

Code:

#!/bin/sh

for FILE in `ls *.cc *.c` # | egrep "printf\ | fprintf"

do
        echo $FILE;                                    #to make sure ls worked
        if [ grep -Fqx '#include <stdio.h>' "$FILE" ] 
        then
                sed '1i\
                #include <stdio.h> ' file > new_file;
                mv new_file file;
        fi
done


chrism01 09-28-2012 07:36 AM

1. you should bookmark & read
http://rute.2038bug.com/index.html.gz
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/

2. here's a start (NB: bash; not sh)
Code:

#!/bin/bash
for file in `find . -name '*.c' -o -name '*.cc' `
do
#      echo $file
        grep printf $file >/dev/null
        if [[ $? -eq 0 ]]
        then
                echo $file
        fi
done

FYI: http://tldp.org/LDP/abs/html/testcon...ml#DBLBRACKETS

HTH :)

colucix 09-28-2012 07:39 AM

Well... here are some notes:

1. Using the ls command to build the list of items in a for loop is not a good idea. The reasons are well explained here. You can simply use filename expansion without the ls command, instead:
Code:

for FILE in *.cc *.c
do
  :
done

2. In the if/then statement if you want to test the result of a command the square brackets must be left out:
Code:

if grep -q '#include <stdio.h>' "$FILE"
then
  :
fi

Take in mind that the opening square bracket is both a shell built-in and an external command by itself and its behaviour resembles that one of the test command. You can verify by typing the following on the command line and look at the results:
Code:

type -a [
Instead when you test a command you simply put the command after the if keyword. In this case it will return an exit status that can be 0 (that means success or true) or any other number, usually 1 (that means unsuccessful or false).

3. Using sed in Linux you don't need to redirect the output to a temporary file, if you want to change the content of the original one. The option -i let you edit the file in place. Eventually you can add a suffix (near the option) so that a (safe) backup copy of the original file is created using the suffix you specified in the command line, e.g.
Code:

sed -i.bck '1\
#include <stdio.h> ' "$FILE"


Said that, your script might be something like:
Code:

#!/bin/sh

for FILE in *.cc *.c
do
    if grep -q printf "$FILE"
        if ! grep -q '#include <stdio.h>' "$FILE"
        then
            sed -i.bck '1i\
            #include <stdio.h> ' "$FILE"
        fi
    fi
done

Note the exclamation point before the command in the if statement: it is the logical NOT operator. Literally it states: if the pattern is NOT found in the file, then.... Hope this helps.

Habitual 09-28-2012 10:00 AM

Ubiquitous bash scripting links...
http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html
http://www.tldp.org/LDP/Bash-Beginne...tml/index.html
http://www.gnu.org/software/bash/man...ode/index.html
http://www.grymoire.com/Unix/Sh.html
http://tldp.org/LDP/abs/abs-guide.pdf
http://www.tldp.org/LDP/abs/html/
http://mywiki.wooledge.org/BashFAQ
http://mywiki.wooledge.org/BashPitfalls

grail 09-28-2012 11:21 AM

I know it is nit picking, but as your learning I think it is valid to mention the following:

1. You have said you are learning bash, then why is it you are using the wrong interpreter?
Code:

#!/bin/sh

Should be

#!/bin/bash

This not to say your script will not work, however by calling the script with sh, which may be a symbolic link to bash, you are telling the interpreter that the
script is POSIX in nature which does mean certain advanced features from bash are not available.

2. If you really want to learn bash, I would also suggest performing the entire task in bash as opposed to calling external commands like grep and sed.

Admittedly the code will be longer but you will learn much more about bash if you force yourself to keep external command out of it.

Just my 2 cents of course :)

calvarado777 09-28-2012 01:44 PM

Thank you!
 
You guys are fantastic! Thanks so much for the reference material too! I am in love with the pitfalls page...

I also just read grail's comment-- so we are shell scripting using bash...and I this is what I understood from that lecture..please correct my wrong assumptions...

Bash is just a variance of shell-- so when I wrote #!/bin/sh I thought that was telling the Bash shell that this file is a shell script ... is that not right?

This is the code that ended up working out for me:

Code:

#!/bin/sh

for FILE in *.cc *.c
do
        if grep -q "printf\|fprintf" "$FILE"
        then
                if ! grep -q '#include <stdio.h>' "$FILE"
                then
                        sed -i.bck '1i\#include <stdio> ' "$FILE"
                fi
        fi

done


grail 09-28-2012 02:39 PM

Quote:

Bash is just a variance of shell-- so when I wrote #!/bin/sh I thought that was telling the Bash shell that this file is a shell script ... is that not right?
Yes bash is a variance just as is csh or ksh, however sh is in reference to the original Bourne Shell where as bash is GNU Bourne-Again SHell which is itself derived from sh.

As you look through the links you have been provided you will find there are several things possible in bash that are not in sh.

Here is a link to the top of the Wooledge site which all deserves to be read at some point:

http://mywiki.wooledge.org/TitleIndex

colucix 09-28-2012 03:00 PM

Well done! Just a comment on this line:
Code:

if grep -q "printf\|fprintf" "$FILE"
the alternate pattern is not really necessary here, since printf is a substring of fprintf. In other words, a line matches printf in both cases (be it printf or fprintf) unless you tell grep to match the whole word using the -w option. In this case you may want to be sure it matches only "printf" or "fprintf" and not - for example - "sprintf", "somethingwithprintfinside" and so on.


All times are GMT -5. The time now is 07:12 PM.