Я хотел бы установить несколько пакетов 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"]
#
потому что это - комментарийppa
затем выполните следующую команду с текстом, включенным кавычками. например. ppa "deadsnakes/ppa"
=> sudo add-apt-repository -y ppa:deadsnakes/ppa &> /dev/null
apt
затем выполните следующую команду с текстом, включенным кавычками. например. apt "tree"
=> sudo apt install --allow-unauthenticated -qqy tree
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
}
Я нуждаюсь в помощи, восполняя пробелы к функции, учитывая мой список требования.
Грамматика, используемая здесь, не делает оболочки, пишущей сценарий никаких одолжений, но будет немного легче проанализировать тот файл при использовании регулярных выражений. Сравнение регулярного выражения 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
Уже существует формат для управления 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
Есть много способов сделать сценарий более сложным и увлекательным.
Есть также много способов очистить скрипт и сделать его более читабельным и понятным для вас.
После небольшого исследования, проб и ошибок, я понял, что могу использовать инструмент 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
Учитывая строку package="$(echo $LINE | cut -d \" -f2)"
, давайте разберем ее.
echo
содержимое строки. cut
, который разбивает содержимое $LINE
на несколько полей на основе заданного разделителя. Разделителем в нашем случае является "
. Мы должны были поместить \
перед "
, потому что символ кавычки должен быть экранирован. tree
. $()
возвращает в 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
}
Это может быть не лучшим решением моей проблемы, которое я перечислил выше, и что это действительно хакерское решение, поэтому если есть лучший, пожалуйста, не стесняйтесь писать обновленный ответ!