使用标准工具

时间:2016-11-07 09:35:52

标签: linux bash shell escaping sh

我正在寻找一种标准工​​具,能够获取所有参数并将其转换为适合在自动生成的bash / sh / zsh脚本中用作多个参数的单个字符串。这样的命令在script-fu的各种学科中非常有用。其用法示例:

% shsafe 'A big \nasty string '\'' $HOME $PATH' 'another string \\'
'A big \nasty string '\'' $HOME $PATH' 'another string \\'

在另一个脚本中使用它:

% sshc host rm 'file/with spaces and $special chars'

sshc包含

#!/bin/bash
# usage: sshc host command [arg ...]
# Escapes its arguments so that the command may contain special 
# characters. Assumes the remote shell is sh-like.
host=$1
shift
exec ssh "$host" "$(shsafe "$@")"

另一个例子:

#!/bin/bash
# Run multiple commands in a single sudo session. The arguments of 
# this script are passed as arguments to the first command. Useful if 
# you don't want to have to type the password for both commands and 
# the first one takes a while to run.
sudo bash -c "pacman -Syu $(shsafe "$@") && find /etc -name '*.pacnew'"

我无法在预先存在的命令中找到适合此问题的解决方案,因此我编写了自己的解决方案,名为shsafe。它使用单引号''完全关闭所有shell扩展的事实,除了'本身。

shsafe

#!/usr/bin/env python

from sys import *

n = len(argv)
if n == 1:
    exit(0)

i = 1
while True:
    stdout.write("'" + argv[i].replace("'", "'\\''") + "'")
    i += 1
    if i == n:
        break
    stdout.write(' ')

stdout.write('\n')

是否有任何标准工具能够对其参数进行此操作?

请注意,带有仅包含%q格式化程序的格式字符串的printf命令对此不够好,因为它不会将多个参数分开:

% printf %q arg1 arg2
arg1arg2

1 个答案:

答案 0 :(得分:1)

我最终找到了一个很好的方法:

% printf "$'%q' " 'crazy string \ $HOME' 'another\ string'
$'crazy\ string\ \\\ \$HOME' $'another\\\ string'

这是一个有点容易出错的问题,到处都是引号,所以它不理想,IMO,但它是一个可以在任何地方工作的可靠解决方案。如果它被大量使用,你总是可以把它变成一个shell函数:

shsafe () {
    printf "$'%q' " "$@"
}