提问人:NevilleDNZ 提问时间:7/11/2023 最后编辑:NevilleDNZ 更新时间:7/11/2023 访问量:51
在打印传递给 bash 函数的所有参数时如何明确引用?但是要注意引用特殊字符,避免使用反斜杠?
How to unambiguously quote when printing all args passed to a bash function? But taking care to quote special characters, avoid using the backslash?
问:
基本上,我需要一个名为 echo_Q(或选项)的 shell 函数,而不是回显带引号的参数列表,同时“[nicely]”如果可能的话,严格避免对任何参数进行任何反斜杠引用。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`' '|' '&' ';' "<"
自然,本地产品: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` | & ; <
在上面的结果中:已经评估了报价,其中必要的空格和报价变得不透明。
我试过了,甚至:printf " %q" "$@"; echo
echo_q(){
sep="";
for arg in "$@"; do
printf "$sep%q" "$arg"
sep=" "
done
echo
}
并获得完全“转义”(冗长)的输出,其中完全避免引用。
echo_q another_script a "b b" etc..
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`' '|' '&' ';' '>'
这是我一直在涉足的一个“简单”的黑客:
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
}
但我希望有一种标准(且更简单)的方法来“很好地”函数的参数......echo
Bash 确实有: ,但我需要的是一个很好地引用一个论点。可悲的是,如此简单的事情让我难以理解。:-(printf "%q"
printf "%Q"
欢迎提示!
答:
3赞
Inian
7/11/2023
#1
Bash 确实支持一种以可以重用为输入 agin 的方式引用参数的方法。参数扩展支持标志(在 bash v4.4 中引入)${parameter@operator}
Q 扩展是一个字符串,它是参数的值,以可重用作输入的格式引用。
set -- a "b b" "c 'c' c" 'd "d" d' "e "'"'"'e'"'"'" e" "ls -ltrd .??* | sort -k5,5 > f.lst" 'file `ls -t $HOME`' '|' '&' ';' "<"
for arg in "$@"; do
printf '%s\n' "${arg@Q}"
done
生产
'a'
'b b'
'c '\''c'\'' c'
'd "d" d'
'e "'\''e'\''" e'
'ls -ltrd .??* | sort -k5,5 > f.lst'
'file `ls -t $HOME`'
'|'
'&'
';'
'<'
评论
4赞
Ivan
7/11/2023
无需循环它,只需执行:对于自定义数组,它将是${@@Q}
${arr[@]@Q}
1赞
Inian
7/11/2023
@Ivan 没错,仅用于演示。
0赞
NevilleDNZ
7/11/2023
尼斯:但是你找到“${arg@Q}”了吗?... 和一本150页的平装小说一样大。man bash
3赞
Inian
7/11/2023
@NevilleDNZ - 它来自实践,你需要知道,你在寻找什么 - gnu.org/software/bash/manual/... (在底部)
2赞
Inian
7/11/2023
是的,如前所述,上面的编码方式,在 shell 上下文中再次重用它是安全的。如果你正在寻找一种特定的格式风格,也许重写你自己的引用逻辑应该是方法
0赞
xpusostomos
7/11/2023
#2
我猜你要做的是执行一个带有一些带引号参数的命令,然后以一种看起来不错的方式将其打印出来,包括 bash 风格的引用。上一张海报的解决方案很好,尽管它没有保留你原来的报价。这里有一个小片段,可能对你有一定用处,可以保持它的精确性:
$ read A <<eof
> a "b b" "c 'c' c" 'd "d" d' "e "'"'"'e'"'"'" e"
> eof
$ echo $A
a "b b" "c 'c' c" 'd "d" d' "e "'"'"'e'"'"'" e"
$ eval echo $A
a b b c 'c' c d "d" d e "'e'" e
printx() {
> for i in "$@"
> do
> echo "$i"
> done
> }
$ eval printx $A
a
b b
c 'c' c
d "d" d
e "'e'" e
评论
echo_Q 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`' '|' '&' ';' "<"
def nicely(): ...
bash
printf %q
${…@Q}