gpt4 book ai didi

bash - 反斜杠在反引号中究竟是如何工作的?

转载 作者:行者123 更新时间:2023-11-29 08:50:40 25 4
gpt4 key购买 nike

来自Bash FAQ :

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 中找到的唯一相关引述是:

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

"$(echo\\a)""$(echo\\\\a)" 情况很简单:反斜杠,转义符,正在逃避自己的强烈反对。因此 \\ 的每个实例在输出中都变成了 \ 。但我很难理解反引号案例的类似逻辑。基本规则是什么?观察到的输出如何遵循它?

最后,一个相关的问题......如果你不引用反引号,你会得到一个“不匹配”的错误:

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

在这种情况下发生了什么?

更新

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

在反引号内,字符前面的反斜杠简单地返回该字符。即,单个反斜杠无效。这对所有字符都是如此, 反斜线本身和反引号除外。对于反斜杠本身,\\ 成为转义反斜杠。它将转义它的下一个字符。

让我们看看这是如何在一个例子中发挥作用的:

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

Try it online!

我们从这个角度来分析一下原来的例子:

echo "`echo \\a`"

这里 \\ 产生一个转义反斜杠,但是当我们“转义”a 时,我们只是返回 a,所以它打印 一个

echo "`echo \\\\a`"

这里第一对 \\ 产生一个转义反斜杠,它被应用于 \,产生一个文字反斜杠。也就是说,前 3 个 \\\ 成为输出中的单个文字 \。剩下的 \a 只产生 a。最终结果是\a

最佳答案

这样的逻辑非常简单。所以我们看bash源码(4.4)本身

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 中的字符串。相同功能的代码如下

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);
}

如果有 \ 字符并且下一个字符是 \ 或反引号或 $ 上面只是做了简单的事情,然后跳过这个 \ 字符并复制下一个字符

所以如果为了简单起见将它转换成python

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 中测试相同内容

$ a=xxx

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

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

关于bash - 反斜杠在反引号中究竟是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57447644/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com