bash 스크립트를 사용하여 선착순 만들기 [닫기]

bash 스크립트를 사용하여 선착순 만들기 [닫기]
#/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을 사용하여 쉽게 수행할 수 있는 작업의 예는 다음과 같습니다. 원래 쉘 스크립트에는 약 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 |
|--------|--------|

관련 정보