Projects/1BIT/summer-semester/IOS-1/xtf
2026-04-14 19:28:46 +02:00

154 lines
3.9 KiB
Bash

#!/bin/sh
#xnecasr00 Roman Nečas
#9.3.2024
export POSIXLY_CORRECT=yes
# Function to display help message
print_help() {
echo "Usage: xtf [-h|--help] [FILTER] [COMMAND] USER LOG [LOG2 ...]"
echo ""
echo "Options:"
echo ""
echo " COMMAND can be one of these:"
echo " list - displays records for the given user."
echo " list-currency - displays sorted list of currencies."
echo " status - displays account status for the given user."
echo " profit - calculates profit for the given user."
echo ""
echo " FILTER can be a combination of:"
echo " -a DATETIME - after: considers records after this date and time (exclusive)."
echo " -b DATETIME - before: considers records before this date and time (exclusive)."
echo " -c CURRENCY - considers records matching the given currency."
echo ""
echo " -h or --help displays this help message."
}
# Function to display error message and exit with code 1
print_error() {
echo "Error: $1" >&2
exit 1
}
# Function to validate date
validate_date() {
date -d "$1" >/dev/null 2>&1 || print_error "Invalid date: $1"
}
USER=""
LOGS=""
COMMAND=""
AFTER_DATE=""
BEFORE_DATE=""
CURRENCY_FILTER=""
# Process arguments
while [ "$#" -gt 0 ]; do
case $1 in
-h|--help)
print_help
exit 0
;;
list|list-currency|status|profit)
if [ -z "$COMMAND" ]; then
COMMAND=$1
else
print_error "Multiple commands provided"
fi
;;
-a)
validate_date "$2"
AFTER_DATE=$2
shift
;;
-b)
validate_date "$2"
if [ -z "$BEFORE_DATE" ]; then
BEFORE_DATE=$2
else
print_error "Multiple 'before' dates provided. Please provide only one 'before' date."
fi
shift
;;
-c)
CURRENCY_FILTER=$2
shift
;;
*)
if [ -z "$USER" ]; then
USER=$1
else
# Use a special character to separate log files
LOGS="$LOGS|$1"
fi
;;
esac
shift
done
# Set default command (list) if none specified
if [ -z "$COMMAND" ]; then
COMMAND="list"
fi
# Check if user is specified
if [ -z "$USER" ]; then
print_error "No user specified."
fi
# Change IFS to handle log files with spaces
OLD_IFS="$IFS"
IFS="|"
# Process logs
for LOG in $LOGS
do
case "$LOG" in
*.gz)
zcat "$LOG" || print_error "Failed to read log: $LOG"
;;
*)
cat "$LOG" || print_error "Failed to read log: $LOG"
;;
esac
done
# Restore IFS
IFS="$OLD_IFS"
# Filter records
awk -v user="$USER" -v after="$AFTER_DATE" -v before="$BEFORE_DATE" -v currency_filter="$CURRENCY_FILTER" '
BEGIN {
FS=";"
}
{
if ($1 == "" || $2 !~ /^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$/ || $3 !~ /^[A-Z]{3}$/ ||
$4 !~ /^-?[0-9]+\.[0-9]{4}$/) {
print "Error: Invalid record format: " $0 > "/dev/stderr"
exit 1
}
}
$1 == user && ($2 > after || after == "") && ($2 < before || before == "") && ($3 ~ currency_filter || currency_filter == "") {
print
}
' |
# Process command
case "$COMMAND" in
list)
cat
;;
list-currency)
awk -F ";" '{print $3}' | sort -u
;;
status)
awk -F ";" '{ currency[$3] += $4 } END { for (cur in currency) { printf "%s : %.4f\n", cur, currency[cur] } }' | sort
;;
profit)
if [ -z "$XTF_PROFIT" ]; then
XTF_PROFIT=20
fi
awk -v profit="$XTF_PROFIT" -F ";" '{ currency[$3] += $4 } END { for (cur in currency) { if (currency[cur] > 0) currency[cur] =
currency[cur] * (1 + profit / 100); printf "%s : %.4f\n", cur, currency[cur] } }' | sort
;;
esac