Note: These code snippets were written and tested in 2008.
FYI: There are some challenging fun problems towards the end. Do check those out.
1. Convert all lower case to upper and vice versa.
tr "[a-z] [A-Z]" "[A-Z] [a-z]" < file
or
#!/usr/bin/perl -w
my @array=<STDIN>;
foreach $line (@array)
{
$line=~tr/A-Za-z/a-zA-z/;
print $line;
}2. Print those lines with PRINT in it.On printing remove all small a.
grep 'PRINT' < file | sed 's/a//'
or
#!/usr/bin/perl -w
my @array=<STDIN>;
foreach $line (@array)
{
if($line=~/PRINT/)
{
$line=~tr/a//d;
print $line;
}
}3. Print only those lines starting with a number and end with a character.
grep "^[0-9].*[A-Za-z]$" temp
or
#!/usr/bin/perl -w
my @array=<STDIN>;
foreach $line (@array)
{
if($line=~/^[0-9].*[A-Za-z]$/)
{
print $line;
}
}4. Remove all multiple occurences of a character like aa->a.
sed 's/\(.\)\1*/\1/g' < file
or
#!/usr/bin/perl -w
my @array=<STDIN>;
foreach $line (@array)
{
$line=~s/(.)\1*/\1/g;
print $line;
}5. Remove all multiple occurences of a word with single. eg: ABS ABS->ABS.
sed 's/\(\<[A-Za-z]*\>\)\( \1\)*/\1/g' file
or
#!/usr/bin/perl -w
my @array=<STDIN>;
foreach $line (@array)
{
$line=~s/(\b[^ ]+\b)(\s\b\1\b)+/\1/g;
print $line;
}6. Replace third occurence of word ABS with XYZ.
sed -n '1h;1!{H;};${g;s/ABS/XYZ/3;p;}' file
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
while($line=~/ABS/g)
{
if(++$i==3) {$p=pos($line);substr($line,$p-3,3)='XYZ';}
}
print $line,"\n";
}7. Replace ABC->CED RTY->WWW.
sed '{s/ABC/CED/g;s/RTY/WWW/g;}'
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
$line=~s/ABC/CED/g;
$line=~s/RTY/WWW/g;
print $line;
}8. If there are 3 lines such tat first line have 'A',second 'B' and third 'C' remove the lines.
sed '/A/ {N; /\n.*B/ { N;/\n.*B.*\n.*C/{s/.*//}}}' file |grep -v "^$"
or
#!/usr/bin/perl -w
@array=<>;
my $size=@array;
my $i=0;
while($i<$size)
{
if($array[$i]=~/A/)
{
if($array[$i+1]=~/B/)
{
if($array[$i+2]=~/C/)
{
$i+=3;
next;
}
}
}
print $array[$i];
$i++;
}9. Print all lines except those from 20 to 30.
awk 'NR<20 {print $0} NR>30 {print $0}' file
or
#!/usr/bin/perl -w
@array=<>;
my $size=@array;
my $i=0;
while($i<$size)
{
if($i<20||$i>30)
{ print $array[$i]; }
$i++;
}10. Remove all C comments from a C file.
sed 's/\/\/.*//' filename | tr '\n' '$' |sed 's/\/\*[^\*]*\*\///g' | tr '$' '\n'
11. Remove all blank lines from a file.
grep -v "^$" file > file
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
if($line!~/^$/)
{
print $line;
}
}12. Print total number of lines in a file.
cat filename | wc -l
or
#!/usr/bin/perl -w
@array=<>;
my $size=@array;
print $size;13. Print all lines from the line having MACS to 26th line.
awk '/MACS/,(NR==26) {print $0}' < file
or
#!/usr/bin/perl -w
@array=<>;
my $size=@array;
for($i=0;$i<$size;$i++)
{
if($array[$i]=~/MACS/)
{
print $array[$i];
while(++$i<size && $i=26)
{ print $array[$i]; }
}
}14. If a line contain MEC enter 'DATA' at the end of the line else enter 'SATA' at the beginning.
awk '/MEC/ {print $0,"DATA";} !/MEC/ {print "SATA",$0;}' filename
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
chop($line);
if($line=~/MEC/)
{print $line."DATA\n";}
else {print "SATA".$line."\n";}
}15. If the line contain HI replace all a->b ad b->c and c->d.
sed '/HI/ {y/abc/bcd/;}' filename
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
if($line=~/HI/)
{$line=~tr/abc/bcd/;}
print $line;
}16. If a file contain word 'XYZ' anywhere in it no matter how many times,print 'Success' once.
awk '/XYZ/ {print "Success";exit;}' < file
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
if($line=~/XYZ/)
{print "Success\n"; exit 0;}
}17. If a file has the word 'ABC' first and somewhere else it has the word XYZ; print success only once.
awk 'BEGIN {a=0;b=0;} /ABC/ {a=1;} /XYZ/ {if(a==1) b=1;} END {if(b==1) print "Success";}' filename
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
if($line=~/ABC/) {$flag=1;}
if($line=~/XYZ/ && $flag==1)
{ print "Success\n"; exit 0;}
}18. Remove all \n from the file.
tr -d "/n" < file > file
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
chop($line);
print $line;
}19. Reverse all lines in a file.
tac file
or
#!/usr/bin/perl -w
@array=<>;
for($i=@array;$i>=0;$i--)
{ print $array[$i]; }20. Given two unique files. Write a script to find their nearest common parent directory path.
#!/bin/bash
find / -type f -name $1>f
find / -type f -name $2>g
count=`wc -c < f`
for((i=1;i<$count;i++));
do
read -n$i a <f
read -n$i b <g
if [ $a == $b ]
then
echo $a > p;
continue;
else
break;
fi
done
cat p | sed 's/\/[^/]*$/\//'or
#!/bin/bash
d=1;
find -name $1 -type f > direct1
find -name $2 -type f > direct2
length=$(wc -c < direct.txt)
while [ $d -le $length ]
do
char1=`cut -c 1-$d < direct1`;
char2=`cut -c 1-$d < direct2`;
if [ $char1 != $char2 ];then
echo $char1 | sed 's/\/[^/]*$/\//'
break
else
d=`expr $d + 1`
continue
fi
doneor
#!/usr/bin/perl -w
my $file1=$ARGV[0];
my $file2=$ARGV[1];
my path;
my $path1=`sudo find / -name $file1 -type f`;
my $path2=`sudo find / -name $file2 -type f`;
my @array1=split //,$path1;
my @array2=split //,$path2;
if(@array1<@array2)
{ $size=@array1; }
else
{ $size=@array2; }
for($i=0;$i<$size;$i++)
{
if($array1[$i] eq $array2[$i])
{ $path=$path.$array1[$i];}
else { last; }
}
$path=~s/\/[^\/]*$/\//;
print $path,"\n";21. Replace all alternate occurances of "printf" with "scanf" in a C code.
awk 'BEGIN{ RS=" "; count=0; } /printf/ { count++; if(count%2==0) { sub(/printf/,"scanf",$0); } } { printf($0" "); }' filename
or
#!/usr/bin/perl -w
@array=<>;
my $x=0;
my $i=0;
foreach $line (@array)
{
while($line=~/printf/g)
{
if(++$x%2==0)
{
push(@ps,pos($line));
}
}
foreach $p (@ps)
{
$p=$p-$i;
substr($line,$p-6,6)='scanf';
$i++;
}
@ps=();
$i=0;
print $line;
}or
#!/usr/bin/perl -w
while($line=<>)
{
$count=0;
$line=~s/printf/++$count%2==0?"scanf":"printf"/eg;
print $line;
}22. List all palindromes in a given text file.
#!/bin/bash
exec 0 < 1;
while read or
do
re=$(echo $or |rev);
if [ $or == $re ]
then
echo $or;
fi
doneor
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
while($line=~/(\w+)\s+/g)
{
$var=reverse($1);
if($var eq $1)
{print $var,"\n";}
}
}23. Given a log file. Find the sum of all numbers appearing in the lines having the word 'REJECT' in it. Also find the no. of such numbers greater than 50.
awk '/REJECT/&&/[0-9]/ {gsub(/[^0-9]+/," ",$0);for(i=1;i<=NF;i++) {sum+=$i; if($i>50) num++;}} END { printf("No. of numbers > 50 : %d \nSum of all numbers : %d\n",num,sum);}' < file
or
#!/usr/bin/perl -w
@array=<>;
foreach $line (@array)
{
if($line=~/REJECT/)
{
while($line=~/([0-9]+)/g)
{
$sum+=$1;
if($1>50) {$num++;}
}
}
}
print $sum,"\n",$num,"\n";*24. Given a log file. For any lines having the word 'ERROR', print the preceding 2 lines & succeeding 2 lines of the line. Do not do this if the line having the word 'ERROR' also has the word 'FIXED'. Use perl.
#!/usr/bin/perl -w
my $line;
my @array = <STDIN>;
my $i=-1;
foreach $line (@array)
{
$i++;
if($line=~m/ERROR/ && $line!~m/FIXED/)
{
print $array[$i-2],$array[$i-1],$array[$i+1],$array[$i+2],"\n";
}
}25. Given a text file. Convert the file using perl such that the first character of each sentence & first character of each line is capital. All other characters should be small.
#!/usr/bin/perl -w
my @lines = <STDIN>;
my $var;
foreach $var (@lines)
{
$var=lc($var);
if($var=~m/^([a-z])/)
{
$a=uc($1);
$var=~s/^[a-z]/$a/;
}
if($var=~m/\.[ ]*([a-z])/)
{
$b=uc($1);
$var=~s/(\.[ ]*)[a-z]/\1$b/g;
}
print $var;
}26. Here's a simple encryption algorithm that you can use to encode secret messages: shift every letter in the message 13 characters towards the end of the alphabet. ("a" becomes "n"; "b" becomes "o"; "x" loops around and becomes "k"; etc.) The beauty of this algorithm is that since the alphabet has 26 letters, you can also decrypt a message by repeating the process and shifting every letter in the message 13 characters towards the end of the alphabet. It's often called "ROT 13" because the algorithm "rotates" each letter 13 places. Write a ROT 13 program that will accept a line of text, print the encrypted message, then decrypt the message and print the result. [Test: does your program work for uppercase and lowercase letters?]
#!/usr/bin/perl -w
@in=<>;
foreach $var (@in)
{
@array=split(//,$var);
for($i=0;$i<=$#array;$i++)
{
if($array[$i]=~/[A-Z]/)
{
$d=ord($array[$i])+13-ord("Z");
if($d>0) {$w=ord("A")-1+$d;})
else {$w=ord($array[$i])+13;}
}
elsif($array[$i]=~/[a-z]/)
{
$d=ord($array[$i])+13-ord("z");
if($d>0) {$w=ord("a")-1+$d;}
else {$w=ord($array[$i])+13;}
}
else {$w=ord($array[$i]);}
$w=chr($w);
print $w;
}
}27. User provides a date in command line. Print all files that have been modified before that date. Use perl. Assume the script is run in the native folder itself.
#!/usr/bin/perl -w
@array=`ls -l`;
my $m;my $d;my $y;
$date=<STDIN>;
($y,$m,$d)=split(/-/,$date);
$date=$d+31*$m+365*$y;
foreach $line(@array)
{
@p=split(/\s+/,$line);
($y,$m,$d)=split(/-/,$p[5]);
$d2=$d+31*$m+365*$y;
if($d2<$date) {print $p[7],"\n";}
@p=();
}28. You have current directory containing set of directories which contain files. One file can reside in many directories.Write script which returns number of unique file names inall the subdirectories of the directory.
find . -type f | awk 'BEGIN{FS="/";}{print $NF;}' | sort | uniq
29. List names of all directories in a folder.
ls -F | grep "/$" | sed 's/\(.*\)\//\1/'
30. Delete all blank lines in a file other than the 1st blank line.
awk 'BEGIN{temp=0;} /^$/ {if(temp==0) {temp=1;print;}} !/^$/ {print;}' file
31. Remove text between 2 angular brackets.
sed 's/<[^<]*>/<>/g; s/<[^<]*$/</g; s/^[^>]*>/>/g;' file
32. Increment all numbers in a file by 1.
#!/usr/bin/perl -w
while($line=<>)
{
if($line=~/[0-9]+/)
{
$line=~s/([0-9]+)/$1+1/eg;
}
print $line;
}33. You are given an array of size N that contains positive and negative numbers. Write a program to find the subsequence(contiguous set of elements) with the largest sum. For example, in tthe array -3 -1 5 -3 2 17 -20 -5 9 11 -2, the subsequence with the max sum is 5 -3 2 17 (sum=21).
#include<stdio.h>
main()
{
int i,j,n,max=0,start=0,end=0;
printf("Enter the no. of numbers : ");
scanf("%d",&n);
int list[n];
printf("Enter the numbers (separated by 'space') : ");
for(i=0;i<n;i++)
{
scanf("%d",&list[i]);
}
for(i=0;i<n;i++)
{
int sum=0;
for(j=i;j<n;j++)
{
sum+=list[j];
if(sum>max)
{
max=sum;
start=i;
end=j;
}
}
}
printf("Maximun sum in a substring : %d",max);
printf("\nSubstring having the maximum sum : ");
for(i=start;i<=end;i++)
printf("%d ",list[i]);
printf("\n");
}34. You are given a set of lines. A line is identified by x,y co-ordinates of its two end points. Write a program to determine the number of intersections and print all the intersections.
#include<stdio.h>
main()
{
int n1,n2=0,i,j,count=0,lines[10][2];
float x1,y1,xx[10],yy[10];
printf("Enter the no. of lines : ");
scanf("%d",&n1);
float x[n1][2];
float y[n1][2];
float m[n1];
float c[n1];
for(i=0;i<n1;i++)
{
printf("Enter x & y coordinates of line %d (separated by 'space'; x1 y1 x2 y2) : ",i+1);
scanf("%f",&x[i][0]);
scanf("%f",&y[i][0]);
scanf("%f",&x[i][1]);
scanf("%f",&y[i][1]);
m[i]=(y[i][0]-y[i][1])/(x[i][0]-x[i][1]);
c[i]=y[i][0]-(m[i]*x[i][0]);
}
for(i=0;i<n1-1;i++)
{
for(j=i+1;j<n1;j++)
{
for(x1=x[j][0];x1<=x[j][1];x1+=0.000001)
{
y1=m[j]*x1+c[j];
if(y1==m[i]*x1+c[i] && x1>=x[i][0] && x1<=x[i][1] && y1>=y[i][0] && y1<=y[i][1])
{
xx[n2]=x1;
yy[n2]=y1;
lines[n2][0]=i+1;
lines[n2][1]=j+1;
n2++;
count++;
break;
}
}
}
}
printf("No. of intersections : %d",count);
printf("\nIntersecting lines : ");
for(i=0;i<n2;i++)
printf("\nline %d & line %d intersect at point (%f,%f)",lines[i][0],lines[i][1],xx[i],yy[i]);
printf("\n");
}35. Given a file with lines having variable length. Modify the file such that each line is 33 characters long (except may be the last line).
sed -n '1h;1!{x;G;x};${x;G;s/\n//g;:a s/\(.\{33\}\)/\1\n/;P;s/\(.*\n\)//;ta}' file
36. Arrange the output of 'ls -ABm' such that each line has 5 fields only.
ls -ABm | awk 'BEGIN{RS=",";count=0;} { sub(/\n/," ",$0); printf($0","); count++; if(count==5) { printf("\n"); count=0; } }'
or
ls -ABm | sed -n '1!g;N;s/\n//g; s/,/,\n/5;P;D;x;'
37. Simulate "find" command using perl without using the perl counterparts for "find".
#!/usr/bin/perl -w
my @options;
my $maxdepth=100;
my $temp=0;
for($i=1;$i<=$#ARGV;$i++)
{
push(@options,$ARGV[$i]);
}
&find($ARGV[0],0);
sub find
{
my ($dir,$depth)=($_[0],$_[1]);
opendir(DIR,$dir) or die "Cannot open directory : $!";
my @files=grep{$_ ne "." && $_ ne ".."} readdir(DIR);
closedir(DIR);
my $file;
foreach $file (@files)
{
my $flag=0;
my $i;
my $path=$dir."/".$file;
for($i=0;$i<$#options;$i+=2)
{
if($options[$i] eq "-maxdepth" && $temp==0)
{ $maxdepth=$options[$i+1]; $temp=1;}
elsif($options[$i] eq "-name")
{
if($file!~/$options[$i+1]/) { $flag=1;last; }
}
elsif($options[$i] eq "-type")
{
if($options[$i+1] eq "f" && -f $path ||
$options[$i+1] eq "d" && -d $path) {}
else { $flag=1;last; }
}
elsif($options[$i] eq "-perm")
{
my $mode=(stat("$path"))[2];
my $perm=sprintf("%04o",$mode & 07777);
if($options[$i+1] ne $perm) { $flag=1;last; }
}
}
if($flag==0) { print $path."\n"; }
if($maxdepth>$depth && -d $path)
{
&find($path,$depth+1);
}
}
}#execution :
#macs@mec:~$ ./fnd ~/macs -name script -type f -perm 0755 -maxdepth 2
#only these options are supported, but others can be added easily.
#any of these options can be used in any order.
38. Simulate 'grep' in perl without using the perl counterpart for 'grep'.
#!/usr/bin/perl -w
my @options;
my @args;
my @array;
my $A_num=0;
my $B_num=0;
my $C_num=0;
my $c=0;
my $n=0;
my $i_=0;
my $o=0;
my $v=0;
my $count=0;
my $before=0;
my $after=0;
my $lastpos=0;
my $pat_flag=0;
my $A_flag=0;
my $B_flag=0;
my $C_flag=0;
for($i=0;$i<=$#ARGV;$i++)
{
if($ARGV[$i]=~/-e/) { $pat=$ARGV[++$i]; $pat_flag=1; }
elsif($ARGV[$i]=~/^-/) { push(@options,$ARGV[$i]); }
else { push(@args,$ARGV[$i]); }
}
for($i=0;$i<=$#options;$i++)
{
if($options[$i]=~/-A/) { $A_num=shift(@args); $A_flag=1; }
if($options[$i]=~/-B/) { $B_num=shift(@args); $B_flag=1; }
if($options[$i]=~/-C/) { $C_num=shift(@args); $C_flag=1; }
if($options[$i]=~/-c/) { $c=1; }
if($options[$i]=~/-n/) { $n=1; }
if($options[$i]=~/-i/) { $i_=1; }
if($options[$i]=~/-o/) { $o=1; }
if($options[$i]=~/-v/) { $v=1; }
}
if($pat_flag!=1) { $pat=shift(@args); }
if(@args)
{
foreach $file (@args)
{
open(FILE,"$file") or die "Cannot open file : $!";
@array=<FILE>;
close(FILE);
&match();
}
}
else
{
@array=<STDIN>;
&match();
}
sub match
{
$lastpos=0;
for($i=0;$i<=$#array;$i++)
{
if( ($array[$i]=~/($pat)/) ||
($i_==1 && $array[$i]=~/($pat)/i) ||
($v==1 && $array[$i]!~/($pat)/) ||
($i_==1 && $v==1 && $array[$i]!~/($pat)/i) )
{
$count++;
if(($before!=0 || $after!=0 ) && $v!=1) { print "--\n"; }
$before=0;
$after=0;
if($A_flag==1 && $C_flag==1 && $A_num<$C_num) { $after=$A_num; }
elsif($C_flag!=1) { $after=$A_num; }
elsif($A_flag!=1) { $after=$C_num; }
else { $after=$C_num; }
if($B_flag==1 && $C_flag==1 && $B_num<$C_num) { $before=$B_num;}
elsif($C_flag!=1) { $before=$B_num; }
elsif($B_flag!=1) { $before=$C_num; }
else { $before=$C_num; }
if($c!=1)
{
for($j=$i-$before;$j<=$i+$after;$j++)
{
if($j>=0 && $j<=$#array)
{
if($v==1 && $j<$lastpos) { next; }
if($before==0 && $after==0 && $#args>0) { print $file.":"; }
if($n==1)
{
my $lineno=$j+1;
if($o==1) { print $lineno; }
elsif($v==1) { print $lineno.":"; }
elsif($before==0 && $after==0 && $#args>0)
{
if($array[$j]=~/^#/) { print ":".$lineno.":"; }
else { print "-".$lineno."-"; }
}
else
{
if($array[$j]=~/^#/) { print $lineno.":"; }
else { print $lineno."-"; }
}
}
if($o!=1) { print $array[$j]; }
else { if($j<$i+$after) { print "-"; } }
}
}
}
if($o==1)
{
if($1) { print ":".$1."\n"; }
}
}
$lastpos=$j;
}
if($c==1)
{
if($#args>0) { print $file.":" }
print $count."\n";
}
$count=0;
}#execution :
#mec@macs:~$ ./grp [options] [PATTERN] [FILE1 FILE2 ..]
#mec@macs:~$ cat FILE | ./grp [options] [PATTERN]
#checks only perl regex. (though actual 'grep' uses basic regex, no idea how to implement that in perl, coz there's lots of things to be considered)
#options included are -A, -B, -C, -c, -n, -i, -o, -v