Created
October 29, 2021 23:36
-
-
Save TekWizely/f14c787fd7ecf7719d2963265a6e7d08 to your computer and use it in GitHub Desktop.
Bash script to parse the output of 'update-alternatives --query'
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# shellcheck shell=bash | |
####################################################################### | |
# SPDX-License-Identifier: MIT | |
# Copyright (c) 2021 TekWizely & co-authors | |
# | |
# Use of this source code is governed by the MIT license. | |
# See the accompanying LICENSE file, if present, or visit: | |
# https://opensource.org/licenses/MIT | |
####################################################################### | |
# VERSION="v1.0.0" | |
####################################################################### | |
# alt_parse_query - Parses the output of 'update-alternatives --query' | |
# | |
# $1 = file to read from (can be process sub) | |
# $2 = debug|trace | |
# | |
# example: | |
# | |
# alt_parse_query <( update-alternatives --query pager ) | |
# | |
function alt_parse_query() { | |
# Reset global vars | |
# | |
ALT_GROUP_LINK= | |
ALT_GROUP_NAME= | |
ALT_GROUP_SLAVE_NAMES=() | |
ALT_GROUP_SLAVE_LINKS=() | |
ALT_GROUP_STATUS= # auto | manual | |
ALT_GROUP_CURRENT_VALUE= | |
ALT_GROUP_CURRENT_INDEX= | |
ALT_GROUP_BEST_VALUE= | |
ALT_GROUP_BEST_INDEX= | |
ALT_GROUP_VALUES=() | |
ALT_GROUP_PRIORITIES=() | |
# TODO Consider moving to serialized arrays for slave values | |
#ALT_GROUP_VALUE_${v}_SLAVE_${s}_VALUE | |
_ALT_PARSE_QUERY_STATE="NAME" | |
local IFS line lineno=0 # 1 on first use | |
while IFS="" read -r line || [ -n "${line}" ]; do | |
((lineno += 1)) | |
if [ "${2:-}" == "trace" ]; then | |
printf "# line NO : %s\n" "${lineno}" | |
printf "# line TEXT: '%s'\n" "${line}" | |
printf "# state : %s\n" "${_ALT_PARSE_QUERY_STATE}" | |
printf "# ---------\n" | |
fi | |
# Returns on !0 return code from state functions | |
# | |
_alt_parse_query_state_"${_ALT_PARSE_QUERY_STATE}" "${line}" || return $? | |
done <"${1}" | |
# Final state should be one of "eof candidate" states | |
# | |
if [ ! "${_ALT_PARSE_QUERY_STATE}" = "MAYBE_ALT_START" ] && [ ! "${_ALT_PARSE_QUERY_STATE}" = "MAYBE_ALT_SLAVES_HEADER" ] && [ ! "${_ALT_PARSE_QUERY_STATE}" = "MAYBE_ALT_SLAVE_ENTRY" ]; then | |
printf "unexpected parse state: %s\n" "${_ALT_PARSE_QUERY_STATE}" >&2 | |
return 2 | |
fi | |
if [ "${2:-}" == "trace" ] || [ "${2:-}" == "debug" ]; then | |
printf "ALT_GROUP_NAME : %s\n" "${ALT_GROUP_NAME}" | |
printf "ALT_GROUP_LINK : %s\n" "${ALT_GROUP_LINK}" | |
printf "ALT_GROUP_SLAVE_NAMES : %s\n" "${ALT_GROUP_SLAVE_NAMES[*]}" | |
printf "ALT_GROUP_SLAVE_LINKS : %s\n" "${ALT_GROUP_SLAVE_LINKS[*]}" | |
printf "ALT_GROUP_STATUS : %s\n" "${ALT_GROUP_STATUS}" | |
printf "ALT_GROUP_CURRENT_VALUE: %s\n" "${ALT_GROUP_CURRENT_VALUE}" | |
printf "ALT_GROUP_CURRENT_INDEX: %s\n" "${ALT_GROUP_CURRENT_INDEX}" | |
printf "ALT_GROUP_BEST_VALUE : %s\n" "${ALT_GROUP_BEST_VALUE}" | |
printf "ALT_GROUP_BEST_INDEX : %s\n" "${ALT_GROUP_BEST_INDEX}" | |
printf "ALT_GROUP_VALUES : %s\n" "${ALT_GROUP_VALUES[*]}" | |
printf "ALT_GROUP_PRIORITIES : %s\n" "${ALT_GROUP_PRIORITIES[*]}" | |
local v=0 | |
while [[ $v -lt ${#ALT_GROUP_VALUES[@]} ]]; do | |
local s=0 | |
while [[ $s -lt ${#ALT_GROUP_SLAVE_NAMES[@]} ]]; do | |
local alt_slave_value_ref="ALT_GROUP_VALUE_${v}_SLAVE_${s}_VALUE" | |
printf "${alt_slave_value_ref} : %s\n" "${!alt_slave_value_ref}" | |
((s += 1)) | |
done | |
((v += 1)) | |
done | |
fi | |
} | |
function _alt_parse_query_state_NAME() { | |
local regex="^Name: (.+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
ALT_GROUP_NAME="${BASH_REMATCH[1]}" | |
_ALT_PARSE_QUERY_STATE="LINK" | |
else | |
printf "unable to parse Name field: %s\n" "${1}" >&2 | |
return 2 | |
fi | |
} | |
function _alt_parse_query_state_LINK() { | |
local regex="^Link: (.+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
ALT_GROUP_LINK="${BASH_REMATCH[1]}" | |
_ALT_PARSE_QUERY_STATE="MAYBE_SLAVES_HEADER" | |
else | |
printf "unable to parse Link field: %s\n" "${1}" >&2 | |
return 2 | |
fi | |
} | |
function _alt_parse_query_state_MAYBE_SLAVES_HEADER() { | |
if [[ "${1}" =~ ^Slaves:$ ]]; then | |
_ALT_PARSE_QUERY_STATE="SLAVE_ENTRY" | |
else | |
_ALT_PARSE_QUERY_STATE="STATUS" | |
_alt_parse_query_state_"${_ALT_PARSE_QUERY_STATE}" "${1}" | |
fi | |
} | |
function _alt_parse_query_state_SLAVE_ENTRY() { | |
local regex="^ ([^ ]+) (.+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
ALT_GROUP_SLAVE_NAMES+=("${BASH_REMATCH[1]}") | |
ALT_GROUP_SLAVE_LINKS+=("${BASH_REMATCH[2]}") | |
# Leave status unchanged | |
else | |
_ALT_PARSE_QUERY_STATE="STATUS" | |
_alt_parse_query_state_"${_ALT_PARSE_QUERY_STATE}" "${1}" | |
fi | |
} | |
function _alt_parse_query_state_STATUS() { | |
local regex="^Status: (.+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
ALT_GROUP_STATUS="${BASH_REMATCH[1]}" | |
_ALT_PARSE_QUERY_STATE="BEST" | |
else | |
printf "unable to parse Status field: %s\n" "${1}" >&2 | |
return 2 | |
fi | |
} | |
function _alt_parse_query_state_BEST() { | |
local regex="^Best: (.+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
ALT_GROUP_BEST_VALUE="${BASH_REMATCH[1]}" | |
_ALT_PARSE_QUERY_STATE="VALUE" | |
else | |
printf "unable to parse Best field: %s\n" "${1}" >&2 | |
return 2 | |
fi | |
} | |
function _alt_parse_query_state_VALUE() { | |
local regex="^Value: (.+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
ALT_GROUP_CURRENT_VALUE="${BASH_REMATCH[1]}" | |
_ALT_PARSE_QUERY_STATE="MAYBE_ALT_START" | |
else | |
printf "unable to parse Value field: %s\n" "${1}" >&2 | |
return 2 | |
fi | |
} | |
# eof candidate | |
function _alt_parse_query_state_MAYBE_ALT_START() { | |
if [[ "${1}" != "" ]]; then | |
printf "expecting blank line to start an alternative entry: %s\n" "${1}" >&2 | |
return 2 | |
fi | |
_ALT_PARSE_QUERY_STATE="ALT_VALUE" | |
} | |
function _alt_parse_query_state_ALT_VALUE() { | |
local regex="^Alternative: (.+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
local alt_value="${BASH_REMATCH[1]}" | |
local alt_index=${#ALT_GROUP_VALUES[@]} # assign before += for 0-based value | |
ALT_GROUP_VALUES+=("${alt_value}") | |
# best alt index | |
# | |
if [ "${alt_value}" == "${ALT_GROUP_BEST_VALUE}" ]; then | |
ALT_GROUP_BEST_INDEX=$alt_index | |
fi | |
# current alt index | |
# | |
if [ "${alt_value}" == "${ALT_GROUP_CURRENT_VALUE}" ]; then | |
ALT_GROUP_CURRENT_INDEX=$alt_index | |
fi | |
_ALT_PARSE_QUERY_STATE="ALT_PRIORITY" | |
else | |
printf "unable to parse Alternative value field: %s\n" "${1}" >&2 | |
return 2 | |
fi | |
} | |
function _alt_parse_query_state_ALT_PRIORITY() { | |
local regex="^Priority: ([0-9]+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
ALT_GROUP_PRIORITIES+=("${BASH_REMATCH[1]}") | |
_ALT_PARSE_QUERY_STATE="MAYBE_ALT_SLAVES_HEADER" | |
else | |
printf "unable to parse alternative Priority field: %s\n" "${1}" >&2 | |
return 2 | |
fi | |
} | |
# eof candidate | |
function _alt_parse_query_state_MAYBE_ALT_SLAVES_HEADER() { | |
if [[ "${1}" =~ ^Slaves:$ ]]; then | |
_ALT_PARSE_QUERY_STATE="MAYBE_ALT_SLAVE_ENTRY" | |
else | |
_ALT_PARSE_QUERY_STATE="MAYBE_ALT_START" | |
_alt_parse_query_state_"${_ALT_PARSE_QUERY_STATE}" "${1}" | |
fi | |
} | |
# eof candidate | |
function _alt_parse_query_state_MAYBE_ALT_SLAVE_ENTRY() { | |
local regex="^ ([^ ]+) (.+)$" | |
if [[ "${1}" =~ $regex ]]; then | |
local slave_name="${BASH_REMATCH[1]}" | |
local slave_value="${BASH_REMATCH[2]}" | |
local slave_name_index= | |
local i=0 | |
while [[ $i -lt ${#ALT_GROUP_SLAVE_NAMES[@]} ]]; do | |
if [ "${ALT_GROUP_SLAVE_NAMES[$i]}" == "${slave_name}" ]; then | |
slave_name_index=$i | |
break | |
fi | |
i=$((i + 1)) | |
done | |
# find it? | |
if [ -n "${slave_name_index}" ]; then | |
local alt_index=$((${#ALT_GROUP_VALUES[@]} - 1)) | |
local slave_value_ref="ALT_GROUP_VALUE_${alt_index}_SLAVE_${slave_name_index}_VALUE" | |
declare -g "${slave_value_ref}"="${slave_value}" | |
#else | |
# printf "unable to match alternative slave Name: %s - skipping\n" "${1}" >&2 | |
fi | |
# Leave status unchanged | |
else | |
_ALT_PARSE_QUERY_STATE="MAYBE_ALT_START" | |
_alt_parse_query_state_"${_ALT_PARSE_QUERY_STATE}" "${1}" | |
fi | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment