究竟反斜杠在反引号内如何工作? [英] Exactly how do backslashes work within backticks?

查看:174
本文介绍了究竟反斜杠在反引号内如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Bash常见问题解答:

反引号内的反斜杠(\)以非显而易见的方式处理:

Backslashes (\) inside backticks are handled in a non-obvious manner:

 $ echo "`echo \\a`" "$(echo \\a)"
 a \a
 $ echo "`echo \\\\a`" "$(echo \\\\a)"
 \a \\a

但是FAQ并没有分解导致这种差异的解析规则.我发现的来自man bash的唯一相关报价是:

But the FAQ does not break down the parsing rules that lead to this difference. The only relevant quote from man bash I found was:

当使用旧式的反引号替换形式时,反斜杠保留其字面意思,除非后面跟有$,`或.

When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or .

"$(echo \\a)""$(echo \\\\a)"的情况很容易:反斜杠(转义字符)正在将自身转义为字面反冲.因此,\\的每个实例在输出中都变为\.但是我在努力理解反引号案例的类似逻辑.基本规则是什么?观察到的输出如何遵循该规则?

The "$(echo \\a)" and "$(echo \\\\a)" cases are easy enough: Backslash, the escape character, is escaping itself into a literal backlash. Thus every instance of \\ becomes \ in the output. But I'm struggling to understand the analogous logic for the backtick cases. What is the underlying rule and how does the observed output follow from it?

最后,一个相关的问题...如果您不引述反引号,则会显示不匹配".错误:

Finally, a related question... If you don't quote the backticks, you get a "no match" error:

$ echo `echo \\\\a`
-bash: no match: \a

在这种情况下是怎么回事?

What's happening in this case?

回复:我的主要问题是,我有一套解释所有行为的规则理论,但是仍然看不到bash中任何已记录的规则如何遵循它.这是我提出的规则....

Re: my main question, I have a theory for a set of rules that explains all the behavior, but still don't see how it follows from any of the documented rules in bash. Here are my proposed rules....

在反引号内,字符前面的反斜杠只是返回该字符.即,单个反斜杠无效.这对于所有字符都是正确的,除了 反冲本身和反引号.在反斜杠本身的情况下,\\变为转义的反斜杠.它将转义其下一个字符.

Inside backticks, a backslash in front of a character simply returns that character. Ie, a single backslash has no effect. And this is true for all characters, except backlash itself and backticks. In the case of backslash itself, \\ becomes an escaping backslash. It will escape its next character.

在示例中让我们看看它是如何进行的:

Let's see how this plays out in an example:

a=xx
echo "`echo $a`"      # prints the value of $a
echo "`echo \$a`"     # single backslash has no effect: equivalent to above
echo "`echo \\$a`"    # escaping backslash make $ literal

打印:

xx
xx
$a

网上试试吧!

让我们从这个角度分析原始示例:

Let's analyze the original examples from this perspective:

echo "`echo \\a`"

此处\\会产生转义的反斜杠,但是当我们转义"时, a我们只是返回a,所以它显示a.

Here the \\ produces an escaping backslash, but when we "escape" a we just get back a, so it prints a.

echo "`echo \\\\a`"

在这里,第一对\\产生一个转义的反斜杠,该反斜杠应用于\,产生一个文字反斜杠.也就是说,前3个\\\在输出中成为单个文字\.其余的\a仅产生a.最终结果是\a.

Here the first pair \\ produces an escaping backslash which is applied to \, producing a literal backslash. That is, the first 3 \\\ become a single literal \ in the output. The remaining \a just produces a. Final result is \a.

推荐答案

这样的逻辑非常简单.因此,我们来看bash源代码(4.4)本身

The logic is quite simple as such. So we look at bash source code (4.4) itself

subst.c:9273

case '`': /* Backquoted command substitution. */
{
    t_index = sindex++;

    temp = string_extract(string, &sindex, "`", SX_REQMATCH);
    /* The test of sindex against t_index is to allow bare instances of
        ` to pass through, for backwards compatibility. */
    if (temp == &extract_string_error || temp == &extract_string_fatal)
    {
    if (sindex - 1 == t_index)
    {
        sindex = t_index;
        goto add_character;
    }
    last_command_exit_value = EXECUTION_FAILURE;
    report_error(_("bad substitution: no closing \"`\" in %s"), string + t_index);
    free(string);
    free(istring);
    return ((temp == &extract_string_error) ? &expand_word_error
                                            : &expand_word_fatal);
    }

    if (expanded_something)
    *expanded_something = 1;

    if (word->flags & W_NOCOMSUB)
    /* sindex + 1 because string[sindex] == '`' */
    temp1 = substring(string, t_index, sindex + 1);
    else
    {
    de_backslash(temp);
    tword = command_substitute(temp, quoted);
    temp1 = tword ? tword->word : (char *)NULL;
    if (tword)
        dispose_word_desc(tword);
    }
    FREE(temp);
    temp = temp1;
    goto dollar_add_string;
}

如您所见,在字符串上调用函数de_backslash(temp);会更新c中的字符串.相同功能的代码如下

As you can see calls a function de_backslash(temp); on the string which updates the string in c. The code the same function is below

subst.c:1607

/* Remove backslashes which are quoting backquotes from STRING.  Modifies
   STRING, and returns a pointer to it. */
char *
    de_backslash(string) char *string;
{
  register size_t slen;
  register int i, j, prev_i;
  DECLARE_MBSTATE;

  slen = strlen(string);
  i = j = 0;

  /* Loop copying string[i] to string[j], i >= j. */
  while (i < slen)
  {
    if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
                              string[i + 1] == '$'))
      i++;
    prev_i = i;
    ADVANCE_CHAR(string, slen, i);
    if (j < prev_i)
      do
        string[j++] = string[prev_i++];
      while (prev_i < i);
    else
      j = i;
  }
  string[j] = '\0';

  return (string);
}

如果有\个字符并且下一个字符是\或反引号或$,则上面的操作很简单,然后跳过此\字符并复制下一个字符

The above just does simple thing if there is \ character and the next character is \ or backtick or $, then skip this \ character and copy the next character

因此,为了简单起见,将其转换为python

So if convert it to python for simplicity

text = r"\\\\$a"

slen = len(text)
i = 0
j = 0
data = ""
while i < slen:
    if (text[i] == '\\' and (text[i + 1] == '`' or text[i + 1] == '\\' or
                             text[i + 1] == '$')):
        i += 1
    data += text[i]
    i += 1

print(data)

相同的输出是\\$a.现在让我们在bash中进行测试

The output of the same is \\$a. And now lets test the same in bash

$ a=xxx

$ echo "$(echo \\$a)"
\xxx

$ echo "`echo \\\\$a`"
\xxx

这篇关于究竟反斜杠在反引号内如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆