ПОС/Предрок 2021

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

Предрок траје 120 минута.

Задатак 2

Поставка

(15п) Написати bash скрипту која проналази све целобројне и реалне константе дефинисане као макрое унутар .c датотека. Констана[sic] се дефинише као макро у формату:

#define nazivKonstante vrednost

Скрипта прима следеће аргументе:

  • једини позициони аргумент је путања до директоријума који треба претражити до призвољне дубине. Овај директоријум и сви његови поддиректоријуми садрже .c датотеке унутар којих треба пронаћи константе дефинисане као макрое;
  • опција -o са аргументом који представља путању до датотеке у коју је потребно уписати у засебном реду nazivKonstante=vrednost за сваку константу која се пронађе;
  • опција -s без аргумента треба да испише збир свих целобројних константи након завршетка скрипте у формату "Збир је: збир";
  • опција -z са аргументом који представља директоријум у коме треба направити датотеку под називом arhiva која садржи компримоване и архивиране само оне .c датотеке у којима је пронађена бар једна константа која је дефинисана као макро.

Опција o је обавезна, док опсије s и z нису обавезне. Исписивати кратке поруке о грешкама у случају некоректних аргумената приликом покретања скрипте и таквим случајевима прекинути рад скрипте.

Решење

#!/bin/bash

dst_path=
zbir=
arh_dir=

while getopts ":o:sz:" opt; do
    case $opt in
        o) dst_path=$OPTARG
            ;;
        s) zbir=1
            ;;
        z) arh_dir=$OPTARG
            ;;
        *) printf -- 'korišćenje: ./skripta.sh -o putanja [-s] [-z arhiva] [-h]\n'
            exit 1
            ;;
    esac
done

shift $(($OPTIND - 1))
src_path="$1"

if [ -z "$src_path" ]; then
    printf -- 'pozicioni argument skripte je obavezan\n'
    exit 2
fi
if [ -z "$dst_path" ]; then
    printf -- 'argument skripte -o je obavezan\n'
    exit 3
fi

temp=$(mktemp)

grep -rE '^#define \w+ [0-9]+(\.[0-9]*)?$' $src_path > $temp # uzmi sve celobrojne ili realne brojeve

sed -E 's/^.*#define (\w+) ([0-9]+(\.[0-9]*)?)$/\1=\2/' $temp > $dst_path

[ $zbir ] && sed -E 's/^.*=(.*)$/\1/' $dst_path | awk '{s += $1} END {print "Zbir je: " s}'

[ ! $arh_dir ] && tar -cvfz arhiva -T <(sed 's|:.*$||' $temp | uniq) # ovo ne radi ako neki od fajlova ima ':' u svom imenu zbog greedy .*, ali to je valjda dovoljno razumna pretpostavka