Как делают меня, масса устанавливает способные пакеты условно из файла?

Цель

Я хотел бы установить несколько пакетов APT с помощью файла.

apt_install_from_file "packages" # assumes 'packages' is a readable file in the $PWD

Примечание: Я понимаю, что существуют другие способы сделать это, и я изобретаю велосипед для разговора, но я надеюсь, что этот путь мог сделать жизни других легче.

Файловая структура

packages:

# ppa
ppa "deadsnakes/ppa"

# packages
apt "tree"

# deb
deb "fzy" [args: "https://github.com/jhawthorn/fzy/releases/download/0.9/fzy_0.9-1_amd64.deb", "$HOME", "fzy_0.9-1_amd64.deb"]

Требования

  1. Проигнорируйте любую строку, которая запускается с # потому что это - комментарий
  2. Если строка запускается с ppa затем выполните следующую команду с текстом, включенным кавычками. например. ppa "deadsnakes/ppa" => sudo add-apt-repository -y ppa:deadsnakes/ppa &> /dev/null
  3. Если строка запускается с apt затем выполните следующую команду с текстом, включенным кавычками. например. apt "tree" => sudo apt install --allow-unauthenticated -qqy tree
  4. Если строка запускается с deb затем захватите текст, включенный кавычками, а также захватите текст, который следует args включенный кавычками.

Текущая функция:

apt_install_from_file() {

    declare -r FILE_PATH="$1"

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    # Install package(s)

    if [ -e "$FILE_PATH" ]; then

        cat < "$FILE_PATH" | while read -r LINE; do
            if [[ "$LINE" == *"#"* || -z "$LINE" ]]; then
                continue
            elif [[ "$LINE" == *"ppa"* || -z "$LINE" ]]; then
                # ppa= Grab text enclosed by quotes following "ppa"
                sudo add-apt-repository -y ppa:"$ppa" &> /dev/null \
                   && sudo apt update
            elif [[ "$LINE" == *"apt"* || -z "$LINE" ]]; then
                package="$LINE" # Grab text enclosed by quotes following "apt"
                sudo apt install --allow-unauthenticated -qqy "$package"
            elif [[ "$LINE" == *"deb"* || -z "$LINE" ]]; then
                #package_name= Grab text enclosed by quotes following "deb"
                #url= Grab text enclosed by quotes following "args"
                #target_path= Grab text enclosed by quotes following "args"
                #file_name= Grab text enclosed by quotes following "args"
                #file_path="$target_path" + "/" + "$file_name"  

                wget $url -O $file_path && \
                   sudo dpkg -i $file_path && sudo apt-get install -f && \
                   sudo rm -rf $file_path && sudo apt autoremove -qqy
            fi
        done

    fi

}

Проблема

Я нуждаюсь в помощи, восполняя пробелы к функции, учитывая мой список требования.

0
задан 8 July 2018 в 07:23

3 ответа

Грамматика, используемая здесь, не делает оболочки, пишущей сценарий никаких одолжений, но будет немного легче проанализировать тот файл при использовании регулярных выражений. Сравнение регулярного выражения Bash сохраняет группы (...) в BASH_REMATCH массив, таким образом, можно, сразу, протестировать на допустимую строку и проанализировать ее. Например:

#! /bin/bash
declare -A regex
regex["comment"]='^#(.*)'
regex["ppa"]='ppa "(.*)"'
regex["apt"]='apt "(.*)"'
regex["deb"]='deb "(.*)" \[args: "(.*)", "(.*)", "(.*)"\]'
while read LINE
do
    if [[ $LINE =~ ${regex[comment]} ]]
    then
        printf "Comment: %s\n" "${BASH_REMATCH[1]}"
        continue
    elif [[ $LINE =~ ${regex[ppa]} ]]
    then
        ppa=${BASH_REMATCH[1]}
        printf "PPA: %s\n" "$ppa"
    elif [[ $LINE =~ ${regex[apt]} ]]
    then
        package=${BASH_REMATCH[1]}
        printf "APT: %s\n" "$package"
    elif [[ $LINE =~ ${regex[deb]} ]]
    then
        package_name=${BASH_REMATCH[1]}
        url=${BASH_REMATCH[2]}
        target_path=${BASH_REMATCH[3]}
        file_name=${BASH_REMATCH[4]}
        file_path="$target_path/$file_name"

        printf "package_name: %s\n" "$package_name"
        printf "url: %s\n" "$url"
        printf "file_path: %s\n" "$file_path"
    fi
done < "$1"

С Вашим файлом в качестве примера:

$ ./foo.sh foo.txt
Comment:  ppa
PPA: deadsnakes/ppa
Comment:  packages
APT: tree
Comment:  deb
package_name: fzy
url: https://github.com/jhawthorn/fzy/releases/download/0.9/fzy_0.9-1_amd64.deb
file_path: $HOME/fzy_0.9-1_amd64.deb
1
ответ дан 28 October 2019 в 23:32

Уже существует формат для управления apt с помощью файла. Это обычный сценарий оболочки.

#!/bin/sh

# Instructions: Run me using sudo: $ sudo install_script.sh
# WARNING: All errors have been muted or thrown out. Guess I don't want to know...

# PPA
add-apt-repository -y ppa:deadsnakes/ppa &> /dev/null
add-apt-repository -y ppa:font-manager/staging &> /dev/null
add-apt-repository -y ppa:fish-shell/release-2 &> /dev/null
add-apt-repository -y ppa:zanchey/asciinema &> /dev/null

# packages
apt install --allow-unauthenticated -qqy tree symlinks

# deb
wget https://github.com/jhawthorn/fzy/releases/download/0.9/fzy_0.9-1_amd64.deb -O /tmp/fzy_0.9-1_amd64.deb
apt --install /tmp/fzy_0.9-1_amd64.deb -qqy
rm /tmp/fzy_0.9-1_amd64.deb

Есть много способов сделать сценарий более сложным и увлекательным.

Есть также много способов очистить скрипт и сделать его более читабельным и понятным для вас.

3
ответ дан 28 October 2019 в 23:32

Предыстория:

После небольшого исследования, проб и ошибок, я понял, что могу использовать инструмент cut в сочетании с echo.

Пример:

Для достижения желаемого результата возьмите следующий пример.

packages:

# packages
apt "tree"

test.sh:

apt_install_from_file() {

    declare -r FILE_PATH="$1"

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    # Install package(s)

    if [ -e "$FILE_PATH" ]; then

        cat < "$FILE_PATH" | while read -r LINE; do

            if [[ "$LINE" == *"#"* || -z "$LINE" ]]; then
                continue
            elif [[ "$LINE" == *"apt"* || -z "$LINE" ]]; then
                package="$(echo $LINE | cut -d \" -f2)"
                echo "$package"
            fi

        done
    fi

}

Использование :

./test.sh packages

[ 1123] Разбивка:

Учитывая строку package="$(echo $LINE | cut -d \" -f2)", давайте разберем ее.

  1. Во-первых, мы echo содержимое строки.
  2. Затем мы передадим этот результат в cut, который разбивает содержимое $LINE на несколько полей на основе заданного разделителя. Разделителем в нашем случае является ". Мы должны были поместить \ перед ", потому что символ кавычки должен быть экранирован.
  3. Затем мы берем второе поле этого разбиения, которое содержит tree.
  4. Наконец, мы сохраняем содержимое того, что $() возвращает в package, для которого это tree (например, $() => tree).

Измененная функция:

apt_install_from_file() {

    declare -r FILE_PATH="$1"

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    # Install package(s)

    if [ -e "$FILE_PATH" ]; then

        cat < "$FILE_PATH" | while read -r LINE; do
            if [[ "$LINE" == *"#"* || -z "$LINE" ]]; then
                continue
            elif [[ "$LINE" == *"ppa"* || -z "$LINE" ]]; then
                ppa="$(echo $LINE | cut -d \" -f2)"
                sudo add-apt-repository -y ppa:"$ppa" &> /dev/null \
                   && sudo apt update
            elif [[ "$LINE" == *"apt"* || -z "$LINE" ]]; then
                package="$(echo $LINE | cut -d \" -f2)"
                sudo apt install --allow-unauthenticated -qqy "$package"
            elif [[ "$LINE" == *"deb"* || -z "$LINE" ]]; then
                package_name="$(echo $LINE | cut -d \" -f2)"
                url="$(echo $LINE | cut -d \" -f4)"
                target_path="$(echo $LINE | cut -d \" -f6)"
                file_name="$(echo $LINE | cut -d \" -f8)"
                file_path="$target_path/$file_name"  

                wget $url -O $file_path && \
                   sudo dpkg -i $file_path && sudo apt-get install -f && \
                   sudo rm -rf $file_path && sudo apt autoremove -qqy
            fi
        done

    fi

}

Вывод:

Это может быть не лучшим решением моей проблемы, которое я перечислил выше, и что это действительно хакерское решение, поэтому если есть лучший, пожалуйста, не стесняйтесь писать обновленный ответ!

1
ответ дан 28 October 2019 в 23:32

Другие вопросы по тегам:

Похожие вопросы: