从 sh 中生成 sh 代码:转义

ike*_*ami 2 escaping sh

我有一个 shell 变量(我们称之为x),其中包含一个带有 shell 元字符的字符串。例如,我可能有

abc  "def's"  ghi
Run Code Online (Sandbox Code Playgroud)

由设置

x='abc  "def'\''s"  ghi'
Run Code Online (Sandbox Code Playgroud)

我想从该字符串构建一个 shell 命令(存储在文件中,而不是执行)。我有什么选择?

echo "prog $x"     >>file     # Doesn't work
echo "prog '$x'"   >>file     # Doesn't work
echo "prog \"$x\"" >>file     # Doesn't work
Run Code Online (Sandbox Code Playgroud)

目前的解决方案使用sed

y=`echo "$x" | sed 's/\([^a-zA-Z0-9._\-\/]\)/\\\\\1/g'`
echo "prog $y" >>file
Run Code Online (Sandbox Code Playgroud)

输出如下(尽管等效输出也是可以接受的):

prog abc\ \ \"def\'s\"\ \ ghi
Run Code Online (Sandbox Code Playgroud)

问题是需要这样做的地方数量正在增加。有人有更好的解决方案吗?

笔记:

  • 必须适用于sh(与 相对bash)并且任何内容都sh可以合理地别名(例如bashsh仿真模式下)。
  • 它必须尽可能便携(Windows 除外)。
  • 使用perl是不可接受的,但使用随处可见的其他 UNIX 工具可能是可接受的。

ike*_*ami 5

sh有功能。

# to_shell_lit() - Creates a shell literal
# Usage:  printf '%s\n' "...$( to_shell_lit "..." )..."
to_shell_lit() {
    printf \'
    printf %s "$1" | sed "s/'/'\\\\''/g"
    printf \'
}
Run Code Online (Sandbox Code Playgroud)

测试:

$ x='abc  "def'\''s"  ghi'

$ printf '%s\n' "$x"
abc  "def's"  ghi

$ printf '%s\n' "prog `to_shell_lit "$x"`"
prog 'abc  "def'\''s"  ghi'

$ printf '%s\n' "prog $( to_shell_lit "`pwd`" )"
prog '/home/ikegami/foo bar'
Run Code Online (Sandbox Code Playgroud)
$ printf '%s\n' "$( to_shell_lit "a'b" )"
'a'\''b'

$ printf '%s\n' "$( to_shell_lit '-n' )"
'-n'

$ printf '%s\n' "$( to_shell_lit '\\' )"
'\\'

$ printf '%s\n' "$( to_shell_lit 'foo
bar' )"
'foo
bar'
Run Code Online (Sandbox Code Playgroud)

带有多个参数的版本:

# to_shell_lit() - Creates a shell literal
# Usage:  printf '%s\n' "$( to_shell_lit "..." "..." "..." )"
to_shell_lit() {
    local prefix=''
    local p
    for p in "$@" ; do
        printf "$prefix"\'
        printf %s "$p" | sed "s/'/'\\\\''/g"
        printf \'
        prefix=' '
    done
}
Run Code Online (Sandbox Code Playgroud)