问题描述
任何人都可以解释为什么下面的例子1工作,当没有使用r
前缀?
我认为只要使用转义序列,就必须使用r
前缀。
示例2和示例3证明了这一点。
# example 1
import re
print (re.sub('\s+', ' ', 'hello there there'))
# prints 'hello there there' - not expected as r prefix is not used
# example 2
import re
print (re.sub(r'(\b\w+)(\s+\1\b)+', r'\1', 'hello there there'))
# prints 'hello there' - as expected as r prefix is used
# example 3
import re
print (re.sub('(\b\w+)(\s+\1\b)+', '\1', 'hello there there'))
# prints 'hello there there' - as expected as r prefix is not used
1楼
因为\\
begin只有当它们是有效的转义序列时才会转义序列。
>>> '\n'
'\n'
>>> r'\n'
'\\n'
>>> print '\n'
>>> print r'\n'
\n
>>> '\s'
'\\s'
>>> r'\s'
'\\s'
>>> print '\s'
\s
>>> print r'\s'
\s
存在'r'或'R'前缀, 字符串中的将根据与标准C使用的规则类似的规则进行解释。已识别的转义序列为:
Escape Sequence Meaning Notes \\newline Ignored \\\\ Backslash (\\) \\' Single quote (') \\" Double quote (") \\a ASCII Bell (BEL) \\b ASCII Backspace (BS) \\f ASCII Formfeed (FF) \\n ASCII Linefeed (LF) \\N{name} Character named name in the Unicode database (Unicode only) \\r ASCII Carriage Return (CR) \\t ASCII Horizontal Tab (TAB) \\uxxxx Character with 16-bit hex value xxxx (Unicode only) \\Uxxxxxxxx Character with 32-bit hex value xxxxxxxx (Unicode only) \\v ASCII Vertical Tab (VT) \\ooo Character with octal value ooo \\xhh Character with hex value hh
永远不要依赖原始字符串作为路径文字,因为原始字符串有一些相当奇特的内部工作,已知在屁股中咬人:
当存在“r”或“R”前缀时,字符串中包含反斜杠后面的字符不做更改,并且所有反斜杠都保留在字符串中。 例如,字符串文字
r"\\n"
由两个字符组成:反斜杠和小写“n”。 字符串引号可以使用反斜杠进行转义,但反斜杠仍保留在字符串中; 例如,r"\\""
是一个有效的字符串文字,由两个字符组成:反斜杠和双引号;r"\\"
不是有效的字符串文字(即使原始字符串也不能以奇数个反斜杠结尾)。具体来说,原始字符串不能以单个反斜杠结尾(因为反斜杠会转义后面的引号字符)。另请注意,后跟换行符的单个反斜杠被解释为字符串的一部分,而不是行继续。
为了更好地说明这最后一点:
>>> r'\'
SyntaxError: EOL while scanning string literal
>>> r'\''
"\\'"
>>> '\'
SyntaxError: EOL while scanning string literal
>>> '\''
"'"
>>>
>>> r'\\'
'\\\\'
>>> '\\'
'\\'
>>> print r'\\'
\\
>>> print r'\'
SyntaxError: EOL while scanning string literal
>>> print '\\'
\
2楼
'r'表示以下是“原始字符串”,即。 反斜杠字符按字面处理,而不是表示对以下字符的特殊处理。
所以'\\n'
是一个换行符
并且r'\\n'
是两个字符 - 反斜杠和字母'n'
写它的另一种方法是'\\\\n'
因为第一个反斜杠逃脱了第二个
写这个的等价方式
print (re.sub(r'(\b\w+)(\s+\1\b)+', r'\1', 'hello there there'))
是
print (re.sub('(\\b\\w+)(\\s+\\1\\b)+', '\\1', 'hello there there'))
由于Python处理不是有效转义字符的字符的方式,并不是所有这些双反斜杠都是必要的 - 例如'\\s'=='\\\\s'
但是对于'\\b'
和'\\\\b'
。
我的偏好是明确地将所有反斜杠加倍。
3楼
并非所有涉及反斜杠的序列都是转义序列。
例如, \\t
和\\f
,但\\s
不是。
在非原始字符串字面,任何\\
不是一个转义序列的一部分,被视为只是另一\\
:
>>> "\s"
'\\s'
>>> "\t"
'\t'
然而, \\b
是转义序列,因此示例3失败。
(是的,有些人认为这种行为很不幸。)
4楼
试试看:
a = '\''
'
a = r'\''
\'
a = "\'"
'
a = r"\'"
\'