如何在打印Bash函数参数时无歧义引用且避免反斜杠
实现友好带引号输出的Shell函数echo_Q
需要实现一个Shell函数echo_Q,输出带引号的参数列表,尽可能避免用反斜杠转义,解决以下痛点:
- 原生
echo会解析引号,导致空格、引号等关键信息丢失 - 基于
printf "%q"实现的echo_q虽能保留参数完整性,但输出包含大量反斜杠,可读性极差
现有方案对比
原生echo示例
echo another_script a "b b" "c 'c' c" 'd "d" d' "e "'"'"'e'"'"'" e" "ls -ltrd .??* | sort -k5,5 > f.lst" 'file `ls -t $HOME`' '|' '&' ';' "<"
输出:
another_script a b b c 'c' c d "d" d e "'e'" e ls -ltrd .??* | sort -k5,5 > f.lst file `ls -t $HOME` | & ; <
基于printf %q的echo_q实现
echo_q(){ sep=""; for arg in "$@"; do printf "$sep%q" "$arg" sep=" " done echo }
输出:
another_script a b\ b c\ \'c\'\ c d\ \"d\"\ d e\ \"\'e\'\"\ e ls\ -ltrd\ .\?\?\*\ \|\ sort\ -k5\,5\ \>\ f.lst file\ \`ls\ -t\ \$HOME\` \| \& \; \>
期望输出
another_script a 'b b' "c 'c' c" 'd "d" d' e\ \"\'e\'\"\ e 'ls -ltrd .??* | sort -k5,5 > f.lst' 'file `ls -t $HOME`' '|' '&' ';' '>'
简洁优化实现
以下是更标准简洁的实现,优先用单引号/双引号包裹参数,仅当参数同时包含单双引号时才使用%q转义,在保证正确性的前提下最大化可读性:
echo_Q() { local sep="" for arg in "$@"; do printf "%s" "$sep" if [[ -z "$arg" ]]; then printf "''" elif [[ "$arg" != *\'* ]]; then printf "'%s'" "$arg" elif [[ "$arg" != *\"* ]]; then printf "\"%s\"" "$arg" else printf "%q" "$arg" fi sep=" " done echo }
逻辑说明
- 空参数直接输出
''避免歧义 - 参数不含单引号:用单引号包裹,无需转义双引号、空格等特殊字符
- 参数不含双引号:用双引号包裹,无需转义单引号、空格等特殊字符
- 参数同时包含单双引号:回退到
printf "%q"转义,确保参数能被Shell正确解析
当前尝试的hack实现
special='$( )*?`<>\|&;;' qq_special='$`' echo_Q(){ sep=""; for arg in "$@"; do printf "$sep"; sep=" " case "$arg" in (*["$special'"'"']*) case "$arg" in (*'"'*) case "$arg" in (*"'"*)printf "%q" "$arg";;; (*)printf "'%s'" "$arg";;; esac;; (*"'"*) case "$arg" in (*"$qq_special"*) printf "%q" "$arg";;; (*) printf '"%s"' "$arg";;; esac;; (*) printf "'%s'" "$arg";;; esac;; (*) printf "%s" "$arg";;; esac sep=" " done echo }
内容的提问来源于stack exchange,提问作者NevilleDNZ
相关产品推荐
相关产品推荐

