命令转义 bash 中的字符串

我需要一个 bash 命令将字符串转换为转义的内容:

echo "hello\world" | escape | someprog

其中,escape 命令将 "hello\world"变成 "hello\\\world"。然后,some prog 可以按照预期使用 "hello\\world"。当然,这只是一个简单的例子,说明了我将要做的事情。

166273 次浏览

您可以使用 perl 替换各种字符,例如:

$ echo "Hello\ world" | perl -pe 's/\\/\\\\/g'
Hello\\ world

根据转义的性质,可以链接多个调用来转义适当的字符。

纯 Bash,使用参数替换:

string="Hello\ world"
echo ${string//\\/\\\\} | someprog

In Bash:

printf "%q" "hello\world" | someprog

例如:

printf "%q" "hello\world"
hello\\world

这也可以通过变量来使用:

printf -v var "%q\n" "hello\world"
echo "$var"
hello\\world

它可能不完全是您想要的,因为它不是任何系统上的标准命令,但是由于我的程序在 POSIX 系统上应该能够很好地工作(如果编译的话) ,所以无论如何我都要提到它。如果您有能力在有问题的机器上编译或添加程序,那么它应该可以工作。

我已经毫无问题地使用它大约一年了,但它可能不会处理一些边缘案件。最具体地说,我不知道它将如何处理字符串中的换行; 可能需要添加 \\n的用例。这个字符列表并不权威,但我相信它涵盖了所有其他内容。

我特别将其作为一个“助手”程序来编写,这样我就可以为诸如 scp命令之类的东西制作一个包装器。

它也可以作为 shell 函数实现

因此,我呈现 escapify.c。我是这样使用它的:

scp user@host:"$(escapify "/this/path/needs to be escaped/file.c")" destination_file.c

请注意: 我制作了这个程序为我个人使用。它还将(可能是错误的)假设,如果给它多个参数,它应该只打印一个未转义的空格,然后继续。这意味着它可以用来正确地传递多个转义参数,但是可能被某些人视为不需要的行为。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char c='\0';
int i=0;
int j=1;
/* do not care if no args passed; escaped nothing is still nothing. */
if(argc < 2)
{
return 0;
}
while(j<argc)
{
while(i<strlen(argv[j]))
{
c=argv[j][i];
/* this switch has no breaks on purpose. */
switch(c)
{
case ';':
case '\'':
case ' ':
case '!':
case '"':
case '#':
case '$':
case '&':
case '(':
case ')':
case '|':
case '*':
case ',':
case '<':
case '>':
case '[':
case ']':
case '\\':
case '^':
case '`':
case '{':
case '}':
putchar('\\');
default:
putchar(c);
}
i++;
}
j++;
if(j<argc) {
putchar(' ');
}
i=0;
}
/* newline at end */
putchar ('\n');
return 0;
}

内置在 ${…@Q}扩展中的 bash 已经添加了一段时间:

echo "hello\\world" | ( read -rsd '' x; echo ${x@Q} )
'hello\world'

转义输出是 bash 格式的,所以可能不是您需要的格式。

参见: https://stackoverflow.com/a/27817504/401059