Skip to content
Merged
5 changes: 3 additions & 2 deletions bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -2240,8 +2240,9 @@ _comp_complete_service()
else
local sysvdirs
_comp_sysvdirs || return 1
_comp_compgen_split -- "$(command sed -e 'y/|/ /' \
-ne 's/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p' \
_comp_compgen_split -- "$(command sed -ne 'y/|/ /' \
-e 's/^.*Usage.*{\(.*\)}.*$/\1/p' \
-e 's/^.*msg_usage.*{\(.*\)}.*$/\1/p' \
"${sysvdirs[0]}/${prev##*/}" 2>/dev/null) start stop"
fi
} &&
Expand Down
6 changes: 4 additions & 2 deletions completions-core/apt-get.bash
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ _comp_cmd_apt_get()
# Prefer `apt-cache` in the same dir as command
local pathcmd
pathcmd=$(type -P -- "$1") && local PATH=${pathcmd%/*}:$PATH
_comp_compgen_split -- "$(apt-cache policy | command sed -ne \
's/^ *release.*[ ,]o=\(Debian\|Ubuntu\),a=\(\w*\).*/\2/p')"
_comp_compgen_split -- "$(apt-cache policy | command sed -ne '
s/^ *release.*[ ,]o=Debian,a=\([[:alnum:]]*\).*/\1/p
s/^ *release.*[ ,]o=Ubuntu,a=\([[:alnum:]]*\).*/\1/p
')"
return
;;
esac
Expand Down
4 changes: 2 additions & 2 deletions completions-core/ebtables.bash
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ _comp_cmd_ebtables()
_comp_compgen -- -W '$targets'
_comp_compgen -a split -- "$("$1" ${table:+-t "$table"} -L \
2>/dev/null | command sed -n -e \
"s/INPUT\|OUTPUT\|FORWARD//" -e "$chain")"
"s/INPUT//;s/OUTPUT//;s/FORWARD//" -e "$chain")"
elif [[ $table == "nat" ]]; then
_comp_compgen -- -W '$targets'
_comp_compgen -a split -- "$("$1" -t "$table" -L 2>/dev/null |
command sed -n -e "s/OUTPUT|PREROUTING|POSTROUTING//" \
command sed -n -e "s/OUTPUT//;s/PREROUTING//;s/POSTROUTING//" \
-e "$chain")"
elif [[ $table == "broute" ]]; then
_comp_compgen -- -W 'ACCEPT DROP'
Expand Down
2 changes: 1 addition & 1 deletion completions-core/fbgs.bash
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ _comp_cmd_fbgs()
;;
-m | --mode)
_comp_compgen_split -- "$(command sed \
-n '/^mode/{s/^mode \{1,\}"\([^"]\{1,\}\)"/\1/g;p}' \
-n '/^mode/{s/^mode \{1,\}"\([^"]\{1,\}\)"/\1/g;p;}' \
/etc/fb.modes 2>/dev/null)"
return
;;
Expand Down
2 changes: 1 addition & 1 deletion completions-core/fbi.bash
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ _comp_cmd_fbi()
;;
-m | --mode)
_comp_compgen_split -- "$(command sed \
-n '/^mode/{s/^mode \{1,\}"\([^"]\{1,\}\)"/\1/g;p}' \
-n '/^mode/{s/^mode \{1,\}"\([^"]\{1,\}\)"/\1/g;p;}' \
/etc/fb.modes 2>/dev/null)"
return
;;
Expand Down
4 changes: 3 additions & 1 deletion completions-core/gnokii.bash
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,11 @@ _comp_cmd_gnokii()
_comp_compgen -Rv all_cmd help -- --help all

# these 2 below are allowed in combination with others
# Note: POSIX.1-2024 started to recommend using two backslashes \\ in
# bracket expressions [...] in POSIX sed for the future compatibility.
local main_cmd
_comp_split -l main_cmd "$(printf '%s\n' "${all_cmd[@]}" |
command sed -e '/--config/d;/--phone/d;s/[][\(){}|^$*+?.]/\\&/g')"
command sed -e '/--config/d;/--phone/d;s/[][\\(){}|^$*+?.]/\\&/g')"
# don't provide main command completions if one is
# already on the command line
local IFS='|'
Expand Down
2 changes: 1 addition & 1 deletion completions-core/gpg.bash
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ _comp_cmd_gpg()
command sed -ne 's@^.*<\([^>]*\)>.*$@\1@p')"
if [[ -e ~/.gnupg/gpg.conf ]]; then
_comp_compgen -a split -- "$(command sed -ne \
's@^[ \t]*group[ \t][ \t]*\([^=]*\).*$@\1@p' \
's@^[[:blank:]]*group[[:blank:]][[:blank:]]*\([^=]*\).*$@\1@p' \
~/.gnupg/gpg.conf)"
fi
return
Expand Down
2 changes: 1 addition & 1 deletion completions-core/gpg2.bash
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ _comp_cmd_gpg2()
command sed -ne 's@^.*<\([^>]*\)>.*$@\1@p')"
if [[ -e ~/.gnupg/gpg.conf ]]; then
_comp_compgen -a split -- "$(command sed -ne \
's@^[ \t]*group[ \t][ \t]*\([^=]*\).*$@\1@p' \
's@^[[:blank:]]*group[[:blank:]][[:blank:]]*\([^=]*\).*$@\1@p' \
~/.gnupg/gpg.conf)"
fi
return
Expand Down
5 changes: 4 additions & 1 deletion completions-core/invoke-rc.d.bash
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ _comp_cmd_invoke_rc_d()

if [[ $cword -eq 1 || $prev == --* ]]; then
# generate valid_options
local IFS='|'
local regex_options="${options[*]}"
IFS=$' \t\n'
_comp_compgen_split -- "$(
tr " " "\n" <<<"${words[*]} ${options[*]}" |
command sed -ne "/$(command sed 's/ /\\|/g' <<<"${options[*]}")/p" |
command grep -E -e "$regex_options" |
sort | uniq -u
)"
_comp_expand_glob services '"$sysvdir"/!(README*|*.sh|$_comp_backup_glob)' &&
Expand Down
2 changes: 1 addition & 1 deletion completions-core/ipmitool.bash
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
_comp_cmd_ipmitool__singleline_help()
{
_comp_compgen_split -- "$("$1" "$2" 2>&1 |
command sed -ne 's/[,\r]//g' -e 's/^.*[Cc]ommands://p')"
command sed -ne $'s/[,\r]//g' -e 's/^.*[Cc]ommands://p')"
}

_comp_cmd_ipmitool()
Expand Down
6 changes: 3 additions & 3 deletions completions-core/iptables.bash
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ _comp_cmd_iptables()
_comp_compgen -- -W '$targets'
_comp_compgen -a split -- "$("$1" ${table:+-t "$table"} -nL \
2>/dev/null | command sed -ne "$chain" \
-e 's/INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING//')"
-e 's/INPUT//;s/OUTPUT//;s/FORWARD//;s/PREROUTING//;s/POSTROUTING//')"
elif [[ $table == "nat" ]]; then
_comp_compgen -- -W '$targets MIRROR SNAT DNAT MASQUERADE'
_comp_compgen -a split -- "$("$1" -t "$table" -nL 2>/dev/null |
command sed -ne "$chain" \
-e 's/OUTPUT|PREROUTING|POSTROUTING//')"
-e 's/OUTPUT//;s/PREROUTING//;s/POSTROUTING//')"
elif [[ $table == "mangle" ]]; then
_comp_compgen -- -W '$targets MARK TOS'
_comp_compgen -a split -- "$("$1" -t "$table" -nL 2>/dev/null |
command sed -ne "$chain" \
-e 's/INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING//')"
-e 's/INPUT//;s/OUTPUT//;s/FORWARD//;s/PREROUTING//;s/POSTROUTING//')"
fi
;;
*)
Expand Down
2 changes: 1 addition & 1 deletion completions-core/lilo.bash
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
_comp_cmd_lilo__labels()
{
_comp_compgen_split -- "$(_comp_awk -F = '$1 ~ /^[ \t]*label$/ {print $2}' \
"${1:-/etc/lilo.conf}" 2>/dev/null | command sed -e 's/\"//g')"
"${1:-/etc/lilo.conf}" 2>/dev/null | command sed -e 's/"//g')"
}

_comp_cmd_lilo()
Expand Down
30 changes: 12 additions & 18 deletions completions-core/lintian.bash
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@

_comp_cmd_lintian__tags()
{
local search tags check_files
local tags check_files
_comp_expand_glob check_files '/usr/share/lintian/checks/*.desc' || return 0

tags=$(_comp_awk '/^Tag/ { print $2 }' "${check_files[@]}")
if [[ $cur == *, ]]; then
search=${cur//,/ }
for item in $search; do
tags=$(command sed -e "s/\<$item\>//g" <<<"$tags")
done
_comp_compgen -aR -- -W "$tags"
_comp_compgen -aR -- -W "$tags" -X "@(${cur//,/|})"
else
[[ $cur == ^.*, ]]
_comp_compgen -aP "${BASH_REMATCH-}" -- -W "$tags"
Expand All @@ -20,22 +16,24 @@ _comp_cmd_lintian__tags()

_comp_cmd_lintian__checks()
{
local match search todisable checks check_files
local match search item todisable checks check_files
_comp_expand_glob check_files '/usr/share/lintian/checks/*.desc' || return 0

checks=$(_comp_awk '/^(Check-Script|Abbrev)/ { print $2 }' \
"${check_files[@]}")
if [[ $cur == *, ]]; then
search=${cur//,/ }
todisable=""
for item in $search; do
match=$(command grep -nE "^(Check-Script|Abbrev): $item$" \
"${check_files[@]}" | cut -d: -f1)
todisable=$(_comp_awk '/^(Check-Script|Abbrev)/ { print $2 }' "$match")
for name in $todisable; do
checks=$(command sed -e "s/\<$name\>//g" <<<"$checks")
done
todisable+=$'\n'$(_comp_awk '/^(Check-Script|Abbrev)/ { print $2 }' "$match")
done
_comp_compgen -aR -- -W "$checks"
_comp_split todisable -- "$todisable"
local IFS='|'
todisable="@(${todisable[*]})"
_comp_unlocal IFS
_comp_compgen -aR -- -W "$checks" -X "$todisable"
else
[[ $cur == ^.*, ]]
_comp_compgen -aP "${BASH_REMATCH-}" -- -W "$checks"
Expand All @@ -44,17 +42,13 @@ _comp_cmd_lintian__checks()

_comp_cmd_lintian__infos()
{
local search infos collection_files
local infos collection_files
_comp_expand_glob collection_files '/usr/share/lintian/collection/*.desc' || return 0

infos=$(_comp_awk '/^Collector/ { print $2 }' \
"${collection_files[@]}")
if [[ $cur == *, ]]; then
search=${cur//,/ }
for item in $search; do
infos=$(command sed -e "s/\<$item\>//g" <<<"$infos")
done
_comp_compgen -aR -- -W "$infos"
_comp_compgen -aR -- -W "$infos" -X "@(${cur//,/|})"
else
[[ $cur == ^.*, ]]
_comp_compgen -aP "${BASH_REAMTCH-}" -- -W "$infos"
Expand Down
6 changes: 3 additions & 3 deletions completions-core/mplayer.bash
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,9 @@ _comp_cmd_mplayer()
case $cur in
-*)
_comp_compgen_split -- "$("$cmd" -noconfig all -list-options 2>/dev/null |
command sed -ne "1,/^[[:space:]]*Name/d" \
-e "s/^[[:space:]]*/-/" -e "s/[[:space:]:].*//" \
-e "/^-\(Total\|.*\*\)\{0,1\}$/!p")"
command sed -e '1,/^[[:space:]]*Name/d' \
-e 's/^[[:space:]]*/-/' -e 's/[[:space:]:].*//' \
-e '/^-\(.*\*\)\{0,1\}$/d;/^-Total$/d')"
;;
*)
_comp_compgen_filedir '@(m?(j)p?(e)g|M?(J)P?(E)G|wm[av]|WM[AV]|avi|AVI|asf|ASF|vob|VOB|bin|BIN|dat|DAT|vcd|VCD|ps|PS|pes|PES|fl[iv]|FL[IV]|fxm|FXM|viv|VIV|rm?(j)|RM?(J)|ra?(m)|RA?(M)|yuv|YUV|mov|MOV|qt|QT|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|og[gmavx]|OG[GMAVX]|w?(a)v|W?(A)V|dump|DUMP|mk[av]|MK[AV]|aac|AAC|m2v|M2V|dv|DV|rmvb|RMVB|mid|MID|t[ps]|T[PS]|3g[p2]|3gpp?(2)|mpc|MPC|flac|FLAC|vro|VRO|divx|DIVX|aif?(f)|AIF?(F)|m2t?(s)|M2T?(S)|mts|MTS|vdr|VDR|xvid|XVID|ape|APE|gif|GIF|nut|NUT|bik|BIK|web[am]|WEB[AM]|amr|AMR|awb|AWB|iso|ISO|opus|OPUS|m[eo]d|M[EO]D|xm|XM|it|IT|s[t3]m|S[T3]M|mtm|MTM|w64|W64)?(.@(crdownload|part))'
Expand Down
6 changes: 3 additions & 3 deletions completions-core/mutt.bash
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ _comp_cmd_mutt__query()
[[ $cur ]] || return 0
local muttcmd=${words[0]}

local querycmd="$("$muttcmd" -Q query_command 2>/dev/null | command sed -e 's|^query_command=\"\(.*\)\"$|\1|' -e 's|%s|'"$cur"'|')"
local querycmd="$("$muttcmd" -Q query_command 2>/dev/null | command sed -e 's|^query_command="\(.*\)"$|\1|' -e 's|%s|'"$cur"'|')"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these backslashed double quotes were there to escape them from the surrounding quoted "$( ... )". But IDK if that's necessary in the first place, or further if actually quoting the surrounding thing is ever necessary (i.e. if it could be written just as $( ... ) instead of "$( ... )"). But if so, let's look into addressing/cleaning up that in another PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inside of $(...) is an independent syntactic context and it's unaffected by the quoting outside of it. I guess the command substitution was originally in the old style `...`, where the quoting was necessary, but the quoting was left after switching to $(...). I've identified the commit: 755041c, where it seems to have been POSIX'ly-incorrect from the beginning, or it might have been copied from an even older code.

Yeah, the outside double-quoting "$()" is also unnecessary on the right-hand side of assignments.

if [[ $querycmd ]]; then
local REPLY
_comp_expand_tilde "$querycmd"
Expand All @@ -120,7 +120,7 @@ _comp_cmd_mutt__filedir()
_comp_cmd_mutt__get_muttrc
muttrc=$REPLY
if [[ $cur == [=+]* ]]; then
folder="$("$muttcmd" -F "$muttrc" -Q folder 2>/dev/null | command sed -e 's|^folder=\"\(.*\)\"$|\1|')"
folder="$("$muttcmd" -F "$muttrc" -Q folder 2>/dev/null | command sed -e 's|^folder="\(.*\)"$|\1|')"
[[ $folder ]] || folder=~/Mail

# Match any file in $folder beginning with $cur
Expand All @@ -131,7 +131,7 @@ _comp_cmd_mutt__filedir()
return
elif [[ $cur == !* ]]; then
spoolfile="$("$muttcmd" -F "$muttrc" -Q spoolfile 2>/dev/null |
command sed -e 's|^spoolfile=\"\(.*\)\"$|\1|')"
command sed -e 's|^spoolfile="\(.*\)"$|\1|')"
if [[ $spoolfile ]]; then
_comp_dequote "\"$spoolfile\"" && spoolfile=$REPLY
cur=$spoolfile${cur:1}
Expand Down
2 changes: 1 addition & 1 deletion completions-core/screen.bash
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ _comp_cmd_screen__sessions()
{
local -a sessions
_comp_split sessions "$(command screen -ls | command sed -ne \
's|^\t\{1,\}\([0-9]\{1,\}\.[^\t]\{1,\}\).*'"$1"'.*$|\1|p')" || return
's|^'$'\t''\{1,\}\([0-9]\{1,\}\.[^'$'\t'']\{1,\}\).*'"$1"'.*$|\1|p')" || return
if [[ $cur == +([0-9])?(.*) ]]; then
# Complete sessions including pid prefixes
_comp_compgen -- -W '"${sessions[@]}"'
Expand Down
2 changes: 1 addition & 1 deletion completions-core/shellcheck.bash
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
_comp_cmd_shellcheck__optarg()
{
local args=$("$1" --help 2>&1 |
command sed -e 's/,/ /g' -ne 's/^.*'"$2"'\>.*(\([^)]*\)).*/\1/p')
command sed -e 's/,/ /g' -ne 's/^.*'"$2"'\([^[:alnum:]].*\)\{0,1\}(\([^)]*\)).*/\2/p')
_comp_compgen -a -- -W '$args'
}

Expand Down
7 changes: 7 additions & 0 deletions test/runLint
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ gitgrep "$cmdstart"'sed\b.*\\[?+]' \
gitgrep "$cmdstart"'sed\b.*\\\|' \
"sed with \|, use POSIX BRE (possibly multiple sed invocations) or another tool instead"

gitgrep '(?:'"$cmdstart"'(?:sed|awk|grep)\b| =~ ).*\\[<>]' \
"\< or \> in regular expressions. Anchors \< and \> are not defined by POSIX. No POSIX alternatives."

# Note: awk defines \b to be an escape sequence for <backspace>
gitgrep '(?:'"$cmdstart"'(?:sed|grep)\b| =~ ).*\\b' \
"\b in regular expressions. Anchor \b is not defined by POSIX. No POSIX alternatives."

# TODO: really nonportable? appears to work fine in Linux, FreeBSD, Solaris
#gitgrep $cmdstart'sed\b.*;' \
# 'sed with ;, use multiple -e options instead (POSIX?) (false positives?)'
Expand Down