Bash-скрипт для управления хэштегом ноты


Я написал простой скрипт для управления хэштегом ноты.

Я не знаком с bash скриптов, поэтому я был бы очень признателен, если кто-то может дать мне несколько советов об этом.

#!/bin/bash

#setting default variable values;
FILE="$HOME""/allnotes.txt"
F_ADD=0
F_LIST=0

while getopts ':t:lf:h:a:' opt; do
    case $opt in
        h)
            echo "Options:"
            echo "  -l              List #tags"
            echo "  -t  <tagname>   Select tag to edit"
            echo "  -f  <filename>  Select file to edit"
            echo "  -a  <text>      Add text with tag without opening editor"
            exit 0  
            ;;
        a)
            F_ADD=1
            TEXT=$OPTARG
            ;;
        l) 
            F_LIST=1
            ;;
        t)
            TAG=$OPTARG
            ;;
        f)
            FILE=$OPTARG
            if [ ! -f "$FILE" ]; then
                echo "Unable to open file $FILE." >&2
                exit 1
            fi
            ;;
        \?)
            echo "Invaild option -$OPTARG. Use option -h for help." >&2
            exit 1
            ;;
        :)
            echo "Option -$OPTARG requires an argument." >&2
            exit 1
            ;;
    esac
done

#If option list grep all lines begining with #
if [ $F_LIST -eq 1 ]; then
    grep  '^#' "$FILE" | tr ' ' '\n' | sort | uniq | more
    exit 0;
fi


#No tag specified
if [ ! $TAG ]; then
    echo 'You must to specify tag. Check -h.' >&2
    exit 1
fi


#Removine leading # form tag if there is one;
TAG=$(echo "$TAG" | sed 's/#\?\(.*\)/\1/g')

#If option add was used add tag to file and exit
if [ $F_ADD -eq 1 ]; then
    echo '#'$TAG >> "$FILE"
    echo $TEXT >> "$FILE"
    exit 1
fi

tmp_err(){
    echo "Failed to create temporary file.\nExiting" >&2
    exit 1;
}

#traping clean function to properly handle tmp files on exit or error
trap clean EXIT

temp_file_1=$(mktemp) || tmp_err
clean(){ rm -f ${temp_file_1};}

temp_file_2=$(mktemp) || tmp_err
clean(){ rm -f ${temp_file_1} ${temp_file_2}; }

DEDITOR='/usr/bin/editor' 

if [ ! -x $DEDITOR ]; then
    DEDITOR='vi'
fi

#escaping some awk special signs
E_TAG=$(echo "$TAG" | sed 's/\([+?^$|*(){}.]\)/\\\1/g')

if [ $? -ne 0 ]; then
    echo "SED error" >&2
    exit 1
fi

#Dividing note file into 2 files.
#1st containing notes starting with tag which we asked for,
#2nd containing the rest.
awk '/^#/{if(/(^|\s+)#'"$E_TAG"'(\s+|$)/){f=1}else{f=0} } {if(f){print >"'${temp_file_1}'"}else{ print >"'${temp_file_2}'"}}' "$FILE" 

if [ $? -ne 0 ]; then
    echo "AWK error. Exiting" >&2
    exit 1
fi

#storing last edit date
EDATE=$(stat -c %y $temp_file_1)


#If the selected tag does not exist, we ask if user want to create it.
if [ ! -s "${temp_file_1}" ];then
    while true; do
        read -p "Tag does not exist. Do you want it to be created? [Y/n]" -n 1 -r
        echo
        if [[ $REPLY =~ ^[Yy]$ ]];then
            echo '#'$TAG > "${temp_file_1}"
            break
        elif [[ $REPLY =~ ^[Nn]$ ]];then    
            exit 0
        fi
    done
fi

#Selecting editor VISUAL > EDITOR > DEDITOR
M_EDITOR=${VISUAL:-${EDITOR:-${DEDITOR}}} 

$M_EDITOR "${temp_file_1}"

EDATE2=$(stat -c %y "$temp_file_1")

#check if last edition date has changed.
if [ "$EDATE" == "$EDATE2" ];then
    echo "No changes to apply."
    exit 0;
fi

#User edited file have to begin with # so if it's not,
#we ask him to edit it
while true; do
    if [ "$(sed -n '1s/^#.*/0/p' ${temp_file_1})" != "0" ]; then
        read -p "Lack of leading # [E]dit or [D]iscard?" -n 1 -r
        echo
        if [[ $REPLY =~ ^[Ee]$ ]];then
            $M_EDITOR "${temp_file_1}"
        elif [[ $REPLY =~ ^[Dd]$ ]];then
            exit 0;
        fi
    else
        break;
    fi
done

#Commiting changes
while true;do
    read -p "Do you want to commit changes? [Y/n]" -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]];then
        cat "${temp_file_1}" "${temp_file_2}" > "$FILE"
        exit 0
    elif [[ $REPLY =~ ^[Nn]$ ]];then
        exit 0
    fi
done


109
3
задан 24 февраля 2018 в 06:02 Источник Поделиться
Комментарии
2 ответа


  1. Использование $(CMD) против `CMD` правильно переназначить команды вывода на переменные.

  2. Общий поток выглядит звук, не т логики принятия решений с вложенными условными операторами.

  3. Мне нравится использование stat чтобы захватить некоторую информацию перед написанием ваших временный файл для производства.

Одна вещь, которая может упростить скрипт, у вас есть два elif указывая скрипт код выхода. Пока не ошибся, использовать тернарный условный шаблон может помочь немного ее подчистить, см. ниже:

while true; do
read -p "Do you want to commit changes? [Y/n]" -n 1 -r
echo

[[ $REPLY =~ ^[Nn]$ ]] && exit 0

if [[ $REPLY =~ ^[Yy]$ ]];then
cat "${temp_file_1}" "${temp_file_2}" > "$FILE"
exit 0
fi
done

2
ответ дан 24 февраля 2018 в 06:02 Источник Поделиться

Цитировать

Все двойные кавычки здесь излишни:


FILE="$HOME""/allnotes.txt"

Эти одинарные кавычки тоже лишние:


DEDITOR='vi'

Есть несколько других примеров тоже.

Не повторяйся

Это повторяется закономерность в коде:


echo "Unable to open file $FILE." >&2
exit 1

Было бы неплохо создать функцию для этого.

Замена рисунка


#Removine leading # form tag if there is one;
TAG=$(echo "$TAG" | sed 's/#\?\(.*\)/\1/g')

Если вы должны пройти, чтобы sedиспользуйте sed ... <<< "$TAG" вместо трубопроводов echo.

В этом примере будет проще, понятнее и быстрее альтернатива:

TAG=${TAG#\#}

Мелкие вещи


  • Можно заменить sort | uniq С одного процесса sort -u.

  • Точка с запятой является избыточным в конце строк, например, в exit 0; и exit 1;.

  • Я не понимаю, почему вы определили clean функция дважды.

1
ответ дан 27 февраля 2018 в 08:02 Источник Поделиться