#/bin/bash
sort(){
for ((i = 0; i<$n; i++))
do
for((j = 0; j<`expr $n - $i - 1`; j++))
do
if [ ${arrival_time[j]} -gt ${arrival_time[$((j+1))]} ]
then
# swap
temp=${arrival_time[j]}
arrival_time[$j]=${arrival_time[$((j+1))]}
arrival_time[$((j+1))]=$temp
temp=${burst_time[j]}
burst_time[$j]=${burst_time[$((j+1))]}
burst_time[$((j+1))]=$temp
temp=${pid[j]}
pid[$j]=${pid[$((j+1))]}
pid[$((j+1))]=$temp
elif [ ${arrival_time[j]} -eq ${arrival_time[$((j+1))]} ]
then
if [ ${pid[j]} -eq ${pid[$((j+1))]} ]
then
temp=${arrival_time[j]}
arrival_time[$j]=${arrival_time[$((j+1))]}
arrival_time[$((j+1))]=$temp
temp=${burst_time[j]}
burst_time[$j]=${burst_time[$((j+1))]}
burst_time[$((j+1))]=$temp
temp=${pid[j]}
pid[$j]=${pid[$((j+1))]}
pid[$((j+1))]=$temp
fi
fi
done
done
}
border(){
z=121
for ((i=0; i<$z; i++))
do
echo -n "-"
done
echo ""
}
findWaitingTime(){
service_time[0]=0
waiting_time[0]=0
for ((i=1; i<$n; i++))
do
z=1
y=`expr $i - $z`
service_time[$i]=`expr ${service_time[$y]} + ${burst_time[$y]} `
waiting_time[$i]=`expr ${service_time[$i]} - ${arrival_time[$i]}`
if [ ${waiting_time[$i]} -lt 0 ]
then
waiting_time[$i]=0
fi
done
}
findTurnAroundTime(){
for ((i=0; i<$n; i++))
do
tat[$i]=`expr ${waiting_time[$i]} + ${burst_time[$i]}`
done
}
findAverageTime(){
sort
findWaitingTime
findTurnAroundTime
total_wt=0
total_tat=0
border
printf "|%-18s|%-20s|%-18s|%-20s|%-18s|%-20s|\n" "Process Id" "Burst time" "Arrival time" "Waiting time" "Turn around time" "Completion time"
border
for ((i=0; i<$n; i++))
do
total_wt=`expr $total_wt + ${waiting_time[$i]}`
total_tat=`expr ${tat[$i]} + $total_tat`
completion_time=`expr ${arrival_time[$i]} + ${tat[$i]}`
printf "|%-18s|%-20s|%-18s|%-20s|%-18s|%-20s|\n" ${pid[$i]} ${burst_time[$i]} ${arrival_time[$i]} ${waiting_time[$i]} ${tat[$i]} $completion_time
#echo "${burst_time[$i]} ${arrival_time[$i]} ${waiting_time[$i]} ${tat[$i]} $completion_time"
done
border
#avgwt=`echo "scale=3; $total_wt / $n" | bc`
echo -n "Average waiting time ="
printf %.3f\\n "$(($total_wt / $n))"
#avgtat=`echo "scale=3; $total_tat / $n" | bc`
echo -n "Average turn around time ="
printf %.3f\\n "$(($total_tat / $n))"
for ((i=0; i<8*n+n+1; i++))
do
echo -n "-"
done
echo ""
for ((i=0; i<$n; i++))
do
echo -n "| "
echo -n "P${pid[$i]}"
echo -n " "
done
echo "|"
for ((i=0; i<8*n+n+1; i++))
do
echo -n "-"
done
echo ""
echo -n "0 "
for ((i=0; i<$n; i++))
do
echo -n "`expr ${arrival_time[$i]} + ${tat[$i]}`"
echo -n " "
done
echo ""
}
n=$(sed -e '1~2d' fcfs1.txt |awk '{ for (i=1; i<=NF; i++) RtoC[i]= (i in RtoC?RtoC[i] OFS :"") $i; } END{ for (i=1; i<=NF; i++) print RtoC[i] }'| awk '{print $1}' |wc -l)
for ((i=0; i<$n; i++))
do
pid[$i]=$(cat fcfs.txt | awk '{print $1}')
arrival_time[$i]=$(cat fcfs.txt | awk '{print $2}')
burst_time[$i]=$(cat fcfs.txt | awk '{print $3}')
done
findAverageTime
fcfs.txt内容是这样的:
1 15 10
2 17 12
如果输入文件只有一个进程脚本工作正常,如果输入文件中只有一个进程时有多个进程脚本给出错误输出
-------------------------------------------------------------------------------------------------------------------------
|Process Id |Burst time |Arrival time |Waiting time |Turn around time |Completion time |
-------------------------------------------------------------------------------------------------------------------------
|1 |5 |10 |0 |5 |15 |
-------------------------------------------------------------------------------------------------------------------------
Average waiting time =0.000
Average turn around time =5.000
----------
| P1 |
----------
0 15
答案1
下面是一个使用 perl 可以轻松完成的事情的示例,向您展示为什么应该学习一种更好的语言来处理文本。您的原始 shell 脚本似乎有大约 128 行代码并且不起作用(或者有任何描述它应该如何工作的注释)。这个 Perl 脚本大约有 57 行(不包括大约 30 行注释)。
我试图尽我所能找出每一行的正确计算,但我完全有可能犯了一些错误 - 你的脚本过于复杂(非常如此)并且重复,并且很难理解它在做什么或者为什么要做某事。请随意更正下面的脚本,或者让我知道正确的计算应该是什么。
$ cat summarise_fcfs.pl
#!/usr/bin/perl
use strict;
# Construct the format string for printf. and the ruler line too.
# Width of each field is just enough to fit its header plus a space on
# both sides.
#my @headers = ("Process ID", "Burst time", "Arrival time",
# "Waiting time", "Turn around time", "Completion time");
# Shorter headers to fit in "standard" 80-column terminal
my @headers = ("Process ID", "Burst", "Arrival", "Waiting", "Turnaround", "Completion");
my $fmt = '|'; my $ruler = '|';
foreach (@headers) {
my $len = length($_);
$fmt .= " %${len}s |";
$ruler .= '-' x ($len + 2) . '|';
};
$fmt .= "\n"; $ruler .= "\n";
my $total_wait = 0;
my $total_tat = 0;
# @data is an Array-of-Arrays (AoA) data structure to hold the values
# for each PID. Also known as a List-of-Lists or LoL. See `man
# perllol` and `man perldsc` for details.
my @data = ();
# @st is a single-dimensional array to hold the service time values
# for each PID. These aren't going to be printed with the printf
# format string, so are kept separately from @data (it's easier than
# extracting an array slice from @data to print for each row)
my @st = ();
# Record counter
my $i = 0;
while(<>) {
chomp;
s/^\s*|\s*$//g; # strip leading and trailing whitespace
s/#.*//; # strip comments if any
next if /^\s*$/; # skip empty lines
my ($pid, $arrival, $burst) = split;
my $st = 0;
if ($i > 0) {
# previous st + previous burst
$st = $st[$i-1] + $data[$i-1][1]
};
my $wait = $st - $arrival;
$wait = 0 if ($wait < 0);
my $tat = $wait + $burst;
my $completion = $arrival + $tat;
# Store the data for the current PID in the @data AoA.
$data[$i] = [ $pid, $burst, $arrival, $wait, $tat, $completion ];
# and store the service time too
$st[$i] = $st;
# keep track of totals and increment the record counter.
$total_wait += $wait;
$total_tat += $tat;
$i++;
};
# All data has been read and processed, now it's time
# to produce some output.
print $ruler, sprintf($fmt, @headers), $ruler;
# sort by arrival time (element 2 of each array in
# @data). Like bash, perl array indices start from zero.
foreach my $row (sort { $data[$a][2] <=> $data[$b][2] } keys @data) {
printf $fmt, @{ $data[$row] };
};
print $ruler, "\n";
printf "Average waiting time = %.3f\n", $total_wait / $i;
printf "Average turn around time = %.3f\n\n", $total_tat / $i;
# Now print a table of completion times (5th element of @data[$row])
# for each PID. Limit to 8 columns (PIDs) per output line so it
# doesn't get ridiculously wide.
my $step = 8; # max number of PIDs per output row
for (my $start_col = 0; $start_col < $i ; $start_col += $step) {
my $end_col = $start_col + $step - 1;
$end_col = $i-1 if $end_col > $i;
# Rebuild headers and ruler line for each $step number of PIDs
my @P_headers = map { "P" . $data[$_][0] } $start_col..$end_col;
my $P_fmt = '|'; my $P_ruler = '|';
foreach (@P_headers) {
#my $len = length($_)+4;
my $len = 6; # is 6 characters enough for the PID?
$P_fmt .= " %${len}s |";
$P_ruler .= '-' x ($len + 2) . '|';
};
$P_fmt .= "\n"; $P_ruler .= "\n";
# and print the current row
print $P_ruler, sprintf($P_fmt, @P_headers), $P_ruler;
printf $P_fmt, map { $data[$_][5] } $start_col..$end_col;
print $P_ruler, "\n";
}
示例输出:
$ ./summarise_fcfs.pl fcfs.txt
|------------|-------|---------|---------|------------|------------|
| Process ID | Burst | Arrival | Waiting | Turnaround | Completion |
|------------|-------|---------|---------|------------|------------|
| 1 | 10 | 15 | 0 | 10 | 25 |
| 2 | 12 | 17 | 0 | 12 | 29 |
|------------|-------|---------|---------|------------|------------|
Average waiting time = 0.000
Average turn around time = 11.000
|--------|--------|
| P1 | P2 |
|--------|--------|
| 25 | 29 |
|--------|--------|