6.11 Q) Write a script
my mail which will call mailx to send messages. The script should take
an optional argument -s(to specify the subject) and one or more arguments
to specify the recipients. If my mail is called without option -s it should
prompt the user for a subject.
A) SUBJECT=""
if getopt s:OPTNAME
#Valid option is 's'
then
#which takes an argument
case $OPTNAME in
s) SUBJECT="$OPTARG";;
# The argument to 's' is SUBJECT
?) echo "Usage: $0 [-s subject] users"
exit 1;
# Exit if invalid option
esac
fi
shift $(($OPTIND - 1))
#Remove the options
USERS="$*"
#The rest of the line
# is the recipients
if [ -z "$USERS" ]
#which is compulsory
then echo "Must specify recipients"
exit 1
#Exit if no recipients
fi
while [ -z "$SUBJECT" ]
#Loop until subject
do
# is not null
printf "Subject (no quotes):"
read SUBJECT
done
mailx -s "$SUBJECT" "$USERS"
$alias l1='ls -l'
7.1Q) By setting a trap on
your login shell, arrange to be given the message Goodbye when you logout.
A) The signal EXIT is sent
to your login shell when you logout, so use trap to perform an echo when
this signal is intercepted:
$ trap 'echo Goodbye'
EXIT
7.2Q) Write a function myusage
which will print the total disk used by your home directory, preceded by
a message reminding you of that directory's pathname.
A) $ myusage() {
> printf "Directory %s uses " $HOME
> du -s $HOME | cut -f 1
> }
7.3Q) Write a script which
will take one argument, assumed to be a filename, and run vi on that file
using exec. If no arguments are given, the script should exit with return
status 1.
A)
#
Check number of arguments
if [ $# -ne 1 ]
# If too few arguments, warn user
then echo $0 requires exactly 1 argument
# and exit with status 1
exit 1
# otherwise run vi
else exec vi $1
fi
7.4Q) Create a script which
will read a single line command and execute it
A) echo "Type a command:"
#Prompt the user ......
read CMD
#read in the command..
eval $CMD
#and run it
ls $HOME
uuencode will take
a file and write to STDOUT a representation of the file containing only
ASCII characters.
7.5Q) You have a long file
called bigdata, which contains control characters, and you wish sam to
have a copy of it. Arrange to send sam a copy via electronic mail.
A) $uuencode
bigdata bigdata | split #splitting into small chunks
$ for i in x??
> do
> mailx -s "File $i" sam <$i
> done
$ cat >makefile
myprogram: prog1.o prog2.o
cc -o myprogram prog1.o prog2.o
prog1.o: prog1.c
cc -c prog1.c
prog2.o: prog2.c
cc -c prog2.c
$make myprogram
$make -n
cc -c prog1.c
cc -c prog2.c
Setting up a terminal
More on Files
Miscellaneous Utilities
Regular Expressions and Filters
Filter: Any command which reads from standard input, and writes data to the standard output.
UNIX programming involves transforming input, which is of known form, to output also of known form. The output depends on the input in a specified manner, and often involves creating a pipeline.
In UNIX , there are rarely unique solutions to problems. Want to choose solution which can be implemented fast and efficiently.
The purpose of commands such
as grep, sed, tr and awk to provide speedy solutions for tasks which are
frequently encountered, and which are difficult ot program using the shell
alone.
Range: Collection of characters which are consecutive within the collating sequence eg b-z
Character classes: letters, numbers, punctuations, marks eg:
[:alnum:]
To capitalize all the lower
case letters in the input:
$ tr "a-z" "A-Z"
or $tr "[:lower:]" "[:upper:]"
$ tr "[:lower:]" "[:upper:]" < /usr/dict/words
Q) Write a filter which will
replace all digits by blank spaces.
A) $tr "[:digit:]"
"
"
The 2nd arg of tr should not be shorter than the first.
$ tr ' ' 'B' replaces all blanks in input with a B.
Q) Write a filter which will
replace all double quotes by single quotes.
A) $ tr '"' "'"
or $ tr \" \'
"[X*5]" ==
"XXXXX"
Q) Write a filter which
will replace all letters in the first half of the alphabet by A and all
in the second half by Z.
A) $ tr "A-Ma-mN-Zn-z"
"[A*26][Z*26]"
Q) Write a filter to delete
all characters from the input which are not letters
A) -c option = non-alph
characters, -d delete
$ tr -cd "A-Za-z" or $ tr -cd "[:alpha:]"
Q) Replace multiple spaces
by single ones
A) $echo " hello
there chris" | tr -s " '
-s squash
hello there chris
BRE is said to match a string
if
* each part of the
BRE with special meaning corresponds to a part of the other string, and
* the other individual
characters in the BRE and the string correspond.
Bracket expression:
Expr enclosed in square brackets. The expression enclosed by [] i
s either a matching : single chars, ranges, char classes
[ax-z[:digit:]] matches a,x,y,z and any digit
or
nonmatching list : [^[:upper:]#]
matches any char which is neither upper case or a #.
[Cc]hris will match Chris or chris
[[:alpha:]] .. 3 char string commencing with a letter.
[[:digit:]][[:digit:]]{{:digit:]]* 2 or more digits
^A.*E$
string starting with A and terminating with an E.
Q) What BRE will match a
string which is just a sequence of digits?
A) ^[[digit:]][[:digit:]]*$
[[:alpha:]]+[[:digit:]]? Any string starting with a letter, consisting only of letters, and terminated optionally by a single digit.
(xyz|ab) \.c Will match either xyz.c or ab.c, and no other string.
Q) Write an ERE which will
match any string which consists wither of only upper-case letters or only
lower-case letters.
A)
^[[:lower:]]+|[[:upper:]]+$
Selecting lines according to their content
grep : A function
to select lines from its input which match a BRE normally given as first
arg.
The BRE is known as a script.
Q)To print out all words
ending in ise or ize from /usr/dict/words
A) $ grep 'i[sz]e$' /usr/dict/words
option
-E, grep will use ERE
instead of BRE.
-F, fixed strings, no
regular expressions
-c instead of copying
matched lines, a count is given
-i ignore
case of letters
-f uses RE in filename
-v reverse behaviors
-l ouput list of
those files containing matching line
Q) How many words in /usr/dict/words
commence with a vowel?
A) $ grep -c '^[AEIOUaeiou]'
/usr/dict/words
or $ grep -ci '^[aeiou]' /usr/dict/words
Q) Suppose you have saved
many mail messages in files in the current directory and u want to check
file(s) whose subject has something to do with examinations. Each mail
msg begins with Subject:
Eg: Subject: Examinations
A) $ grep -l '^Subject:
.*[Ee][Xx][Aa[Mn]' *
or
$ grep -li '^Subject: .*exam' *
Note: files with counterexamples
and hexameters will be chosen too.
sed : {address command arguments} where address(which lines of input to take action) & arguments are optional
Addresses: empty-match all
lines
number-match inputline number
num1, num2- match all lines in range[num1-num2]
$-match last input line
/BRE/-match any line matched by BRE
-f file arg
p copy pattern space explicitly
to STDOUT
-n no output
at all
$ sed '1,4d' deletes lines 1-4 from input
$ sed 's/Chris/Sam/g' will change all occurences of Chris to Sam
$ sed 's/^= /?/' change each equals symbol at start of line to ?
$ sed 's/[:punct:]//g' removes all punctuation
Q) Write a sed command that
will remove all whitespace which terminates lines.
A) $ sed 's/[:blank:]*$//'
Q) Write a filer which will
precede each word in /usr/dict/words which contains a capital letter by
an asterisk.
A) $ sed '/[A-Z]/s/^/*/'
</usr/dict/words [A-Z] specify addresses
or
$ sed '/[A-Z]/s/^/*/' /usr/dict/words
Q) Write a filter which will output the last line of the input prepended
by The last line is
A) $ sed -n '$s/^/The
last line is /p'
$ is last line of input, command p to print
-f str : str is used as prefix
instead of xx
-s silent suppress size
pr
-n number Uses number decimal
digits to form filenames for the file pieces. The default is
2.
Q) Split /usr/dict/words
into three files called words00, words01 and words02, first 2 containing
10000 lines and final one the rest.
A) $csplit -f words /usr/dict/words
10001 20001
To check length
$ wc words??
Q) Split at line 1000 and
then repeatedly every 1000 lines up to maximum of 2 times.
A) $ csplit -s /usr/dict/words
1000 {2}
$ wc -l xx??
999
1000
1000
rest
Q) Split /usr/dict/words
into three files called w0, w1, and w2, each containing roughly equal number
of lines
A) $ LINES=$ (wc
-l < /usr/dict/words )
$ ONETHIRD=$(( $LINES/3 ))
$ TWOTHIRDS=$(( $ONETHIRD * 2 ))
$ csplit -f w -n 1 /usr/dict/words $ONETHIRD $TWOTHIRDS
Q) Split /usr/dict/words
into two files, the first containing all words starting with chars up to
and including m, the second starting with n thru z.
A) $split /usr/dict/words
'/^[Nn]/'
Q) File book contains text
for a book, with eachof the 10 chapters starting with a line
Chapter #: adghasf
Split this file into several
files,c alled chapter00, etc one for each chapter.
A) $csplit -f chapter
book '/ ^Chapter/' {9}