【问题标题】:Command to escape a string in bash在 bash 中转义字符串的命令
【发布时间】:2011-02-20 17:32:28
【问题描述】:

我需要一个 bash 命令,它将字符串转换为转义的内容。这是一个例子:

echo "hello\world" | escape | someprog

转义命令将"hello\world" 变成"hello\\\world"。然后, someprog 可以按预期使用"hello\\world"。当然,这是我真正要做的事情的简化示例。

【问题讨论】:

  • 逃跑的本质是什么?换句话说,哪些字符需要转义?您是否正在寻找 C++ 风格的转义(其中制表符替换为 \t、换行符替换为 \n、引号替换为 \" 等)?如果没有明确定义问题,则很难提供帮助。
  • 这个问题可能意味着十几种不同的东西。如果您确切说明您正在寻找哪种转义方式,而不是让我们猜测,这将有所帮助。
  • 问题是特定于使用 \\ 表示 \。有一个可接受的答案。

标签: bash escaping


【解决方案1】:

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

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

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

【讨论】:

  • 为什么不使用 sed? $echo "hello\world" |sed 's/\\/\\\\/'
  • @Octopus,这也是一个有效的选项。我碰巧更喜欢 perl,但是是的,它也可以。
【解决方案2】:

纯 Bash,使用参数替换:

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

【讨论】:

  • 这种方式“hello world”不会转义为“hello\ world” - 接受答案中的 printf 方法可以做到这一点。
【解决方案3】:

在 Bash 中:

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

例如:

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

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

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

【讨论】:

  • 请注意,%q 在大约 2012 年之前被破坏了十多年。它与 ~ 存在问题。还有便携式sed单线器stackoverflow.com/a/20053121/1073695
  • sed 确实更好,因为它也可以避开美元符号
  • @untore: a='abc$def":'; printf '%q\n' "$a" 结果为 abc\$def\":(美元符号被转义)。这是 Bash 4.3(我在 Bash 3.2 中得到了相同的结果)。你用的是什么版本?
  • 转义美元符号只需使用单引号,例如:printf "%q" 'he$l&lo\world'
  • bash 的printf '%q\n' text 引用bash 格式的文本(并且对于当前语言环境),因此只有在他们的someprog 具有与@ 完全相同的引用语法时,这才适用于OP 的情况987654333@ 这不太可能。
【解决方案4】:

它可能不是你想要的,因为它不是任何人系统上的标准命令,但由于我的程序应该在 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;
}

【讨论】:

    【解决方案5】:

    前段时间添加了一个 bash buitin:

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

    转义输出为 bash 格式,因此可能不是您需要的。

    另请参阅:https://stackoverflow.com/a/27817504/401059

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-19
      • 2012-02-06
      • 2021-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      相关资源
      最近更新 更多