变量扩展引起的反斜杠应该如何处理? [英] How should a backslash resulting from variable expansion be treated?

查看:114
本文介绍了变量扩展引起的反斜杠应该如何处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用所有可以找到的shell运行了以下命令(*shsh实现的名称);尽管我希望所有人都能打印match,但结果却不一致.我不知道哪种行为是正确和可靠的.

I ran the following command (*sh being the name of a sh implementation) with all the shells I could find; although I was expecting all to print match, I got inconsistent results. I don't know which behavior is correct and reliable.

*sh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'


使用 Ubuntu仿生软件仓库中的破折号(和ash;这是破折号的符号链接) )


With dash from Ubuntu bionic's repo (and ash; which is a symbolic link to dash)

$ dash -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match

使用bash 4.4.20(1)-发行版(x86_64-pc-linux-gnu)和5.0.11(1)-发行版(arm-unknown-linux-androideabi)

With bash 4.4.20(1)-release (x86_64-pc-linux-gnu) and 5.0.11(1)-release (arm-unknown-linux-androideabi)

$ bash -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match

使用ksh版本AJM 93u + 2012-08-01和版本JM 93t + 2010-03-05(已随SunOS omniosce 5.11预先安装)

With ksh Version AJM 93u+ 2012-08-01, and Version JM 93t+ 2010-03-05 (comes preinstalled with SunOS omniosce 5.11)

$ ksh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match

使用ksh @(#)PD KSH v5.2.14 99.07.13.2(OpenBSD 6.6上的默认外壳,以及其Linux端口)

With ksh @(#)PD KSH v5.2.14 99.07.13.2 (the default shell on OpenBSD 6.6, and its Linux port)

$ ksh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$

使用lksh @(#)LEGACY KSH R56 2018/01/14,mksh @(#)MIRBSD KSH R56 2018/01/14(在Ubuntu bionic上这些是不同的二进制文件)和mksh @(#)MIRBSD KSH R57 2019/03/01

With lksh @(#)LEGACY KSH R56 2018/01/14, mksh @(#)MIRBSD KSH R56 2018/01/14 (these are different binaries on Ubuntu bionic), and mksh @(#)MIRBSD KSH R57 2019/03/01

$ lksh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$ mksh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$ 

最高为0.13.1

$ posh -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$ 

使用yash 2.46

With yash 2.46

$ yash -c 'case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
$ 

并使用zsh 5.4.2(x86_64-ubuntu-linux-gnu)和5.7.1(arm-unknown-linux-androideabi);模拟sh

And with zsh 5.4.2 (x86_64-ubuntu-linux-gnu) and 5.7.1 (arm-unknown-linux-androideabi); emulating sh

$ zsh -c 'emulate sh; case "$1" in $2) echo match; esac' _ 'f\oo' 'f\\oo'
match


我迷失了 POSIX的Shell命令语言规范 ;仍无法找到我的问题的简单答案:应如何以全局模式解释由变量扩展产生的转义反斜杠?是\\还是\?还是未指定?


And I'm lost in POSIX's Shell Command Language specification; couldn't find a straightforward answer to my question yet: How should an escaped backslash resulting from a variable expansion be interpreted in a glob pattern? As \\ or as \? Or is it unspecified?

案例条件构造它说:

按照从case语句的开始到结尾的顺序,每个标记化合物列表的 pattern 均应进行波浪号扩展,参数扩展,命令替换和算术扩展,并且根据

In order from the beginning to the end of the case statement, each pattern that labels a compound-list shall be subjected to tilde expansion, parameter expansion, command substitution, and arithmetic expansion, and the result of these expansions shall be compared against the expansion of word, according to the rules described in Pattern Matching Notation (which also describes the effect of quoting parts of the pattern)

请注意,这并不是说模式会被删除引号;但在模式匹配表示法"下,它表示:

Notice it doesn't say patterns are subjected to quote removal; but under Pattern Matching Notation, it says:

A<反斜杠>字符应转义以下字符.转义的<反斜杠>应该被丢弃

A <backslash> character shall escape the following character. The escaping <backslash> shall be discarded

但是并不清楚这种模式是否是扩展的结果是否仍然会发生.

But it doesn't clarify if that still happens when the pattern is a result of expansion.

对于任何有兴趣的人,标准尚不清楚;他们会在较新的版本中对其进行修改.以下是指向POSIX错误报告的一些链接,其中对该问题进行了广泛讨论.

For anyone who's interested, the standard is unclear on this; they'll amend it in newer versions though. Below are some links to POSIX bug reports where this issue was discussed broadly.

  • 0001234: in most shells, backslash doesn't have two meaning wrt pattern matching
  • 0001190: backslash has two special meanings in the shell and only loses one of them in bracket expressions
  • 0000985: quote removal missing from case statement patterns and alternative expansions

推荐答案

也许此参考资料可以解决您的问题.来自 POSIX的Shell命令语言规范-在模式匹配表示法下该子句指出,

Perhaps this bit of reference can clear things up for your question. From the POSIX's Shell Command Language specification - under Pattern Matching Notation the clause states,

2.13.1 匹配单个字符的模式

<backslash>字符应转义以下字符.转义的<backslash>将被丢弃.如果模式以未转义的<backslash>结尾,则不确定模式是否不匹配或模式被视为无效

A <backslash> character shall escape the following character. The escaping <backslash> shall be discarded. If a pattern ends with an unescaped <backslash>, it is unspecified whether the pattern does not match anything or the pattern is treated as invalid

上述规则适用于使用case语句以及使用test构造在bash中使用==全局匹配运算符的模式.

The above rule applies to patterns while using the case statements and when using the the == glob match operator in bash using test construct.

因此,由于您的$2在进行模式匹配时保持不加引号,因此f\\oo的文字值将永远丢失并被解释为f\oo.

So since your $2 remains unquoted while undergoing pattern match, the literal value of f\\oo is lost forever and gets interpreted as f\oo.

为了清理起见,shell在引用删除期间保留了您的字面值,并且仅当在此模式匹配规则中应用传递的参数时,这种行为才会表现出来.

Just to clear things up, the shell has preserved your literal value during quote removal and just when applying the passed argument in this pattern matching rule, this behavior is exhibited.

这篇关于变量扩展引起的反斜杠应该如何处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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