Thank you @Aki, I'll try to explain a few things.
I use parameter expansions a lot (described in the "Parameter Expansion" section of the Bash manual) because it's much more efficient (faster) than calling an external application such as sed for example. Calling an external application in a loop may be a huge obstacle to performance. It's not that sed or grep are slow, they are very fast on their own, it's the cost of calling them repeatedly.We can use This method replaces grep and sed:This method also replaces sed (it sanitizes the first argument by removing characters that are not digits, lowercase ASCII letters, -, + and . in accordance with the Debian package naming policy).while <condition is true> <execute body>
read returns false on end-of-file (end of apt output)RESULT is an indexed array variable (-a attribute). One way to populate an array is to add values directly to it, i.e. RESULT+=( "<value>" )
apt is run in a subshell, while is run in the current environment. This is different from pipelining apt output to while in that it allows variable values to be retrieved outside of while. CompareIt takes more time to explain the code than to write it ![Smile :)]()
I will be happy to answer any questions, also about the AWK programming language.
I use parameter expansions a lot (described in the "Parameter Expansion" section of the Bash manual) because it's much more efficient (faster) than calling an external application such as sed for example. Calling an external application in a loop may be a huge obstacle to performance. It's not that sed or grep are slow, they are very fast on their own, it's the cost of calling them repeatedly.
Code:
$> FIELD="APT-Sources: https://deb.debian.org/debian bookworm/main amd64 Packages"$> echo "$FIELD"APT-Sources: https://deb.debian.org/debian bookworm/main amd64 Packages$> sed 's/^APT-Sources: //' <<<"$FIELD"https://deb.debian.org/debian bookworm/main amd64 Packages$> echo "${FIELD#APT-Sources: }"https://deb.debian.org/debian bookworm/main amd64 Packages
set -x
to trace what happensCode:
$> FIELD="APT-Sources: https://deb.debian.org/debian bookworm/main amd64 Packages"$> set -x ### start trace$> AREA="${FIELD#APT-Sources: }"+ AREA='https://deb.debian.org/debian bookworm/main amd64 Packages'$> [[ "$AREA" == *\ * ]] && AREA="${AREA#* }" AREA="${AREA%% *}"+ [[ https://deb.debian.org/debian bookworm/main amd64 Packages == *\ * ]] ### test if AREA contains spaces+ AREA='bookworm/main amd64 Packages' ### remove characters before and up to first space in AREA+ AREA=bookworm/main ### remove characters until the last space encountered from the end$> set +x ### return to normal execution (stop trace)+ set +x$> declare -p AREA ### display attributes (none) and value (bookworm/main) of AREA variabledeclare -- AREA="bookworm/main"
Code:
$> set -x$> time { [[ "$FIELD" != "${FIELD#APT-Sources: }" ]] && echo "${FIELD#APT-Sources: }"; }+ [[ APT-Sources: https://deb.debian.org/debian bookworm/main amd64 Packages != \h\t\t\p\s\:\/\/\d\e\b\.\d\e\b\i\a\n\.\o\r\g\/\d\e\b\i\a\n\ \b\o\o\k\w\o\r\m\/\m\a\i\n\ \a\m\d\6\4\ \P\a\c\k\a\g\e\s ]]+ echo 'https://deb.debian.org/debian bookworm/main amd64 Packages'https://deb.debian.org/debian bookworm/main amd64 Packagesreal0m0,000suser0m0,000ssys0m0,000s$> time { grep -q "^APT-Sources: " <<<"$FIELD" && echo "${FIELD#APT-Sources: }"; }+ grep -q '^APT-Sources: '+ echo 'https://deb.debian.org/debian bookworm/main amd64 Packages'https://deb.debian.org/debian bookworm/main amd64 Packagesreal0m0,003suser0m0,003ssys0m0,000s$> time { grep -q "^APT-Sources: " <<<"$FIELD" && sed 's/APT-Sources: //' <<<"$FIELD"; }+ grep -q '^APT-Sources: '+ sed 's/APT-Sources: //'https://deb.debian.org/debian bookworm/main amd64 Packagesreal0m0,005suser0m0,004ssys0m0,002s
Code:
$> set -- "a*b &c&&&-d+é.f@" ### set the first positional parameter $1$> echo "${1//[^0-9a-z\-+.]}" ### delete all (//) characters NOT (^) [range 0-9 or range a-z or - or + or .]abc-d+.f$> LANG="C.utf8" sed 's/[^0-9a-z+.\-]//g' <<<"$1"abc-d+.f
read returns false on end-of-file (end of apt output)
Code:
while IFS='' read -r FIELD; do ### loop on apt output, keep spaces at start and end of line (IFS=''), ### keep backslashes (-r), assign value of FIELD variable : ### bodydone < <(apt show -- "*${PTRN:-firmware}*" 2>/dev/null) ### the value of PTRN is "firmware" if PTRN is empty. Redirect error messages to /dev/null
apt is run in a subshell, while is run in the current environment. This is different from pipelining apt output to while in that it allows variable values to be retrieved outside of while. Compare
Code:
$> declare -a RESULT$> printf '%s\n' " aaa bbb" "ccc ddd " | while IFS='' read -r FIELD; do RESULT+=( "$FIELD" ); done$>declare -p RESULTdeclare -a RESULT ### while is run in a subshell, RESULT is unchanged in the current environment$> while IFS='' read -r FIELD; do RESULT+=( "$FIELD" ); done < <(printf '%s\n' " aaa bbb " "ccc ddd "; TESTVAR="in_a_subshell")$> declare -p RESULTdeclare -a RESULT=([0]=" aaa bbb " [1]="ccc ddd ")$> declare -p TESTVARbash: declare: TESTVAR: not found

I will be happy to answer any questions, also about the AWK programming language.
yes, becausenote: I suspect that the way the wc command calculates the number of words is biased because it does not interpret the code syntax.
and I tend to condense AWK writing, e.g.A word is a non-zero-length sequence of printable characters delimited by white space.
FNR==NR{if (/^Architecture: /){if ($2=="'"$ARCH"'" || $2=="all"){a=1}
could be writtenFNR == NR {if (/^Architecture: /) {if ($2 == "'"$ARCH"'" || $2 == "all") {a = 1}
Statistics: Posted by fabien — 2024-06-16 16:43