LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   simple Shell program for pro's ..but need some help (https://www.linuxquestions.org/questions/linux-software-2/simple-shell-program-for-pros-but-need-some-help-142511/)

Software 02-05-2004 01:06 AM

simple Shell program for pro's ..but need some help
 
Hi all .. i'm having these qustions in one of the assignment at school , and i'm stuck at some point

I know i might have dome a terouble mistakes in both specially the first one there is lots of stuff missing , but i'm just a begginer and i don'n know how to solve that , and the assignment is really worth it !! it's 10% of the final grade !! know what i mean !!

i'd really apprecaite the help , coz i have to hand it in after about 12 hours !!

the programs have to be in ( sh )

the first questions says :
-------------------------------------------------------------------------------------------------------------------------------------
Comment counter
Your shell script called comcount should take 1 or more arguments: the names of text files to check.
For example: comcount *.c

The program should open argument in turn and count the number of comments, i.e lines containing the strings either // or /*. Note: modification, you need not deal with C++ coments of the form '//'. Note that you are supposed to count the number of comments, not the number of lines of comment text. In your documentation you should comment on the difference between these alternative goals.

As extra features, you should count: the number of words of comment text, and the number of unique words of comment text. (Note: as discussed in class, you do not need to count the number of lines of comment text.)

Your program output should be a set of lines each containing a file name followed by a number, exactly as follows. Make sure your default output follows this format exactly.

e.g.

% comcount foo.c
foo.c
13
98
11

where these are the number of comments (13 in this case), the number of the number of words (98) and the number of unique words (11)
---------------------------------------------------------------------------------------------------------------------------------------
and this is the code i wrote for it is :

#/bin/sh
echo Enter the name of the file :
read cFile > file1
cat file1 > temp
num=0
set -f
for i in temp
do
if (i == /*)
then
num=`expr $num + 1`
fi
done
echo $num
wc -w temp
uniq -c temp
rm temp file1
---------------------------------------------------------------------------------------------------------------------------------------
and the second questions is :

File mod checker

Write and test a shell script called checker that is supposed check if any files in a directory have been modified, without making duplicate copies of them. The idea is to compute a checksum (using cksum) for each file and save these checksums in one special file within the directory. When the program is executed, if any file has a different or missing checksum, the name of the file is reported and a copy of the file is saved in a ``tarball'' (discussed in class)/ Save your archived data in a director called "Backups". One futher subtlety is that you should skip the calculation for any file whose name ends in .var or .tar or .z
---------------------------------------------------------------------------------------------------------------------------------------
and the code i wrote for it is :

#!/bin/sh

if (ls * | grep tarball.tar )
then
cksum * > file1
cat file1 | grep -v '*.tar' | grep -v '*.Z' | grep -v '*.var' | grep -v temp1 | grep -v checksums | grep -v file1 | grep -v tarball.tar > temp1
rm file1

if (!(diff checksums temp1 > /dev/null))
then
diff checksums temp1 > difference
#cat temp1 > checksums
cat difference | tr -d '[0-9-]' | cut -b 3- > tp
sort tp | uniq > name
cat name
for i in `cat name`
do
tar -rf tarball.tar $i
done
rm tp
rm difference
rm name
cat temp1 > checksums
fi
rm temp1

else
cksum * > file1
cat file1 | grep -v '*.tar' | grep -v '*.Z' | grep -v '*.var' | grep -v file1 > checksums
ls * | grep -v '*.tar' | grep -v '*.Z' | grep -v '*.var' | grep -v file1 | grep -v checksums > temp2
for i in `cat temp2`
do
tar -rf tarball.tar $i
done
echo The files are backed up and no things have been made
# rm file1 temp2
fi
---------------------------------------------------------------------------------------------------------------------------------------

Thanks alot , i really appreciate any help ..

Software 02-05-2004 10:02 AM

.

AMMullan 02-06-2004 12:27 AM

K i've been playing with the 1st one (sorry, just found your post) and this is what I have so far:

Code:

#! /bin/bash
                                                                                                 
echo -n "Enter the name of the file: "
read FILE
                                                                                                 
  COMM_COUNT=`cat $FILE | grep "/*" | wc -l | awk '{print $1}'`
  WORD_COUNT=`cat $FILE | wc -w | awk '{print $1}'`
                                                                                                 
echo -n "Amount of comments: "
  echo "$COMM_COUNT"
echo -n "Amount of words: "
  echo "$WORD_COUNT"

I'm unsure of how to get a count of uniq lines ( i tried your method, uniq -c foo.c, but it doesn't seem to work, just print the file with a 1 on the front...)

I'll play with the 2nd one and see what I can do

Software 02-06-2004 09:04 AM

Thanks for replying :)

actually in the first question , you are supposed to count the words of the comment , not the words of the file , i tried to write some thing , but i don't know what's wrong with it , it seems to have some syntax error ,
anyway for counting the words there should be some thing that starts reading the words after the first comment sign /* and writing these words to file , and after that we put like an if statment that stops writing to the file when it sees */ which is the end of the comment ..
and for the uniq words ,, it will get the uniq words of this file that we created ( not the file given , we need the uniq words in the comment )
programing in shell is just so effective and so stupid in the same time , i mean you'll get an error some times , just because you added a space !!
this kills me :cry:

can i ask you some thing , what does (awk) do ?

AMMullan 02-06-2004 04:16 PM

I only have a litle knowledge of awk (it is a very powerfult tool but one I haven't had time to learn properly). I use it to filter words:

Code:

$: echo "The quick brown fox" | awk '{print $1}'
The

$: echo "The quick brown fox" | awk '{print $3}'
brown

$: echo "The quick brown fox" | awk '{print $2 $3}'
quickbrown

$: echo "The quick brown fox" | awk '{print $3 " " $4}'
brown fox

as for your problem: try putting a set -x at the very start of your script - that will show you in detail where the script is going wrong...

Let me know how ya go :)

homey 02-06-2004 05:42 PM

This should get you started.....

Code:

#!/bin/bash

#find the lines which start and end with "/*"
#remove the "/*" from output
cat /home/text.txt |grep ^[\/][\*] | sed -e 's/^.\{2\}\(.*\).\{2\}$/\1/' > file.txt

#count the number of lines which start and end with "/*"
cat /home/file.txt |wc -l > file1.txt

#count the number of words from the lines that start and end with "/*"
cat /home/file.txt |wc -w >> file1.txt

#count the number of unique words which are from the comment lines.
cat /home/file.txt | tr ' ' '\012' |sort | uniq |wc -l >> file1.txt


AMMullan 02-06-2004 06:12 PM

Good one homey

Didn't even think about tr'ing the blank spaces - and now I know how to use uniq...

Cheers

homey 02-06-2004 06:20 PM

Hope that's something like what he had in mind. It was fun. :)

Software 02-07-2004 03:18 AM

AMMullan thanks for explaining some of the awk work ..

wow homey .. quite nice and brief !! I guess my code now looks so stupid
:p .. well.. i admit it , it was !! hehe

but i didn't really understand what was going on in this part

grep ^[\/][\*] | sed -e 's/^.\{2\}\(.*\).\{2\}$/\1/'

here grep is " greping " what ?? and what does sed do , with all these arguments ? it helped solving the problem quite fast and efficient , do you mind explain it a little ..

and in the translation code : tr ' ' '\012'
i didn't get why you put them ..


thanks alot ,, i really enjoy learning this stuff .. it just makes you feel so powerful , doesn't it ?
actually i am a microsoft windows user , but now that i know linux , i think there is no way of comparing the two , in terms of having kinda control over your system , and getting more to the core of the real stuff , not just a " human machien who knows how to deal with the " that's it - programs "

thanks for the help .. and waiting to have more fun with the second one .. if you guys suggest working on some thing that is not hard for

:newbie: i would love to do it ..

AMMullan 02-07-2004 04:05 AM

K well i'll help explain a little (kinda forgotten some stuff due to learniing C)

the tr ' ' '\012' just replaces every instance of whitespace with a new line (tr ' ' '\n' would've worked too)..

As for the grep ^[\/][\*] | sed -e 's/^.\{2\}\(.*\).\{2\}$/\1/'... I couldn't explaing it as clearly as I used to so i'll leave that for homey :)

If you want to see an example of a server "monitor" let me know, as i've written one in bash (uses nmap, very kewl script that took a while when i was a newbie)

homey 02-07-2004 09:34 AM

I'll try to explain. :)

grep ^[\/][\*] | sed -e 's/^.\{2\}\(.*\).\{2\}$/\1/'

grep ^[\/][\*] ......
grep.... search for an item which I will determine.
The carrot ( ^ ) says the item is at the beginnng of any line.
[\/] This was a problem as the "/*" are special characters used by the program. Therefore instead of using a normal term like grep "frog" , I had to add the "\" to make the program ignore them. I had to use "/" and "*" separately in case there is a line in your text which just starts with a "/" .

The pipe ( | ) just sends stuff on over the next command which is sed
's/^.\{2\}\(.*\).\{2\}$/\1/'
Here we use s to substitute one item for another on each of the lines that grep found for us. The comment lines start and stop with comments which you don't want counted as words. Therefore we use sed ( streaming editor ) to get rid of those comments ( /* ) before sending our line to the temporary file.
So use the carrot ( ^ ) to find something at the beginning of the line. In this case exactly two characters of any kind .\{2\}. We can say any kind because grep already found the line and we know it starts with "/*" .
The next part \(.*\) includes any part of the line which comes after the first two charaters.
The next part .\{2\}$ defines exactly two characters at the end of the line. We use the ( $ ) to say end of line.
/\1/ This would probably be less confusing if you had some spaces in there like this "/ \1 /" . Remember you are doing substitution. What gets substituted is a complete line goes to a line with two characters chopped of from the start and end.
So this part \1 is the body of text in that line. The other stuff is just not added here and that is how you drop it.

I hope that clears it up a bit :)

AMMullan 02-07-2004 04:52 PM

Ummm homey, i just ran it on the project i'm orking on and it ONLY comes up with the commented lines that start with /* - what happens if he has a line with a comment half-way thru? Also it only show the 1st line of the comment...

I'll have a play aswell - it's so kewl seeing the power of sed :)

homey 02-07-2004 05:53 PM

Argh!!!!! sorry to say I didn't test that good enough. :(
You could smack the program writer and tell them to put comments at the beginning of the line or you could try this....

Code:

#!/bin/bash

#find the lines which start and end with "/*"
#remove the "/*" from output
cat /home/text.txt |grep '[\/][\*]\(.*\)[\/][\*]' | \
awk -F[\/][\*]  '{print $2}' > file.txt

#count the number of lines which start and end with "/*"
cat /home/file.txt |wc -l > file1.txt

#count the number of words from the lines that start and end with "/*"
cat /home/file.txt |wc -w >> file1.txt

#count the number of unique words which are from the comment lines.
cat /home/file.txt | tr ' ' '\012' |sort | uniq |wc -w >> file1.txt


Looking_Lost 02-07-2004 05:56 PM

if you want a directiory listing exclunding certain types you can do

dirListing=`find /myfile/directory -type f ! -name *.tar ! -name *.z ! -name ! -name *.var`

then basename to get the pure names of the files.

homey 02-08-2004 09:08 AM

Quote:

If you want to see an example of a server "monitor" let me know, as i've written one in bash (uses nmap, very kewl script that took a while when i was a newbie)
Hey AMMullan,
Let's see that script if you don't mind.


All times are GMT -5. The time now is 09:50 AM.