bash 的 printf %q 是否有任何 csh 替代方案?

Is there any csh alternative for printf %q of bash?

Bash 的内置命令 printf 支持 %q 格式字符串,它转义 shell 输入的变量内容。

我尝试了一些选项::q只转义space,gnu printf不支持%q

目前,我使用以下代码:

set valq = `echo $val:q | bash -c 'read q;printf %q "$q"'`
/path/to/executable $valq 

我不喜欢依赖 bash 的 csh 脚本。是否有任何 csh 本机解决方案?

谢谢。


这是一个测试代码,用于说明我遇到的问题。

wrapper.csh

#!/bin/csh -f
set i = 1
set tst1 = ""
set tst2 = ""
while ( $i <= $#argv )
    set arg = "$argv[$i]"
    set tst1 = ($tst1:q $arg:q)
    set arg2 = `echo $arg:q | bash -c 'read q;printf %q "$q"'`
    set tst2 = "$tst2:q $arg2:q"
    @ i = $i + 1
end
echo "====case 1===="
./test.csh $tst1:q
./test.csh $tst1
./test.csh $tst2
echo "====case 2===="
csh -cf "./test.csh $tst1"
csh -cf "./test.csh $tst1:q"
csh -cf "./test.csh $tst2"

test.csh

#!/bin/csh -f
echo -n "TEST ARG:"
set i = 1
while ($i <= $#argv)
    echo -n "${i}:$argv[$i] "
    @ i = $i + 1
end
echo

测试结果1: >./wrapper.csh "a ()" b c

====case 1====
TEST ARG:1:a () 2:b 3:c
TEST ARG:1:a 2:() 3:b 4:c
TEST ARG:1:a\ 2:\(\) 3:b 4:c
====case 2====
Badly placed ()'s.
Badly placed ()'s.
TEST ARG:1:a () 2:b 3:c

测试结果2: bash>./wrapper.csh "'\"a ()" b ccsh>./wrapper.csh "'"'"'"a ( ) " b c

====case 1====
TEST ARG:1:'"a () 2:b 3:c
TEST ARG:1:'"a 2:() 3:b 4:c
TEST ARG:1:\'\"a\ 2:\(\) 3:b 4:c
====case 2====
Unmatched '.
Unmatched '.
TEST ARG:1:'"a () 2:b 3:c

测试总结:

只需使用/path/to/executable "$val".

更新

如果在"(如csh -cf "test.csh $tst1")中扩展变量,并且要保留特殊字符和多个单词,则必须确实引用这些单词。但是 bash 的特殊 printf 并不是必不可少的;我们可以做到G。与:

set tst1q=`printf " '%s'" $tst1:q`
csh -cf "test.csh $tst1q"

(没有%q的正常printf)。

更新

要同时允许 "',您可以在最初执行

    set s='s/[] "$&-*;<>?`|~[]/\&/g'

bash -c 'read q;printf %q "$q"' 替换为 wrapper.csh 中的 sed "$s"

正则表达式

[] "$&-*;<>?`|~[]

是一个括号表达式[]括起来的字符列表。它匹配单个字符,该字符将通过替换 \& 加上反斜杠作为前缀(特殊字符 & 指的是匹配的字符)。我没有包含字符 ,^(它们被 printf %q 转义,但在 csh 中不需要),而我包含了 ~(它没有被 printf %q 转义,但需要在 csh 中 - 尝试 wrapper.csh "~").