Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python正则表达式查找XML 1.0不支持的字符不会返回任何结果_Python_Xml_Regex_Unicode_Python 3.x - Fatal编程技术网

Python正则表达式查找XML 1.0不支持的字符不会返回任何结果

Python正则表达式查找XML 1.0不支持的字符不会返回任何结果,python,xml,regex,unicode,python-3.x,Python,Xml,Regex,Unicode,Python 3.x,我正在编写一个Python3.2脚本,以查找Unicode XML格式的文本文件中在XML 1.0中无效的字符。文件本身不是XML 1.0,因此它可以轻松包含1.1及更高版本支持的字符,但使用它的应用程序只能处理XML 1.0中有效的字符,因此我需要找到它们 XML 1.0不支持\u0001-\u0020范围内的任何字符,但\u0009、\u000A、\u000D和\u0020除外。除此之外,\u0021-\uD7FF和\u010000-\u10FFFF也是受支持的范围,但不支持其他范围。在Py

我正在编写一个Python3.2脚本,以查找Unicode XML格式的文本文件中在XML 1.0中无效的字符。文件本身不是XML 1.0,因此它可以轻松包含1.1及更高版本支持的字符,但使用它的应用程序只能处理XML 1.0中有效的字符,因此我需要找到它们

XML 1.0不支持\u0001-\u0020范围内的任何字符,但\u0009、\u000A、\u000D和\u0020除外。除此之外,\u0021-\uD7FF和\u010000-\u10FFFF也是受支持的范围,但不支持其他范围。在Python代码中,我用以下方式定义正则表达式模式:

re.compile("[^\u0009\u000A\u000D\u0020\u0021-\uD7FF\uE000-\uFFFD\u010000-\u10FFFF]")
但是,下面的代码在我的示例文件中找不到已知的坏字符(\u0007,“bell”字符)。不幸的是,我无法提供示例行(专有数据)

我认为问题出在两个地方之一:要么是一个糟糕的正则表达式模式,要么是我如何打开文件并逐行读取,即编码问题。当然,我可能错了

下面是相关的代码片段

processChunkFile()
采用三个参数:
chunkfile
是指向文件的绝对路径(在本例中为原始文件的500000行“块”),该文件可能包含也可能不包含坏字符
outputfile
是指向要将输出写入的可选、预先存在的文件的绝对路径
verbose
是一个布尔标志,用于启用更详细的命令行输出。代码的其余部分只是获取命令行参数(使用
argparse
)并将单个大文件分解成更小的文件。(原始文件通常大于4GB,因此需要将其“分块”。)

Python
\u
转义仅为四位数字,因此u+0100后跟两个u+0030位零。对于BMP以外的字符,请使用大写字母-U转义,并包含八位数字:

\U00010000-\U0010FFFF
请注意,在Python的“狭义构建”中,字符串基于UTF-16代码单元,BMP之外的字符作为两个代理代码单元处理,这一点和您的表达式通常不起作用。(窄版是Windows的默认版本。谢天谢地,他们已经放弃了Python 3.3。)

它可以很容易地包含1.1及更高版本支持的字符

(尽管XML 1.1在编码为数字字符引用时只能包含这些字符
&#…
,因此文件本身可能仍然格式不正确。)

打开(文件“r”)

您确定chunkfile是在
locale.getpreferredencoding
中编码的吗

原始文件通常大于4GB,因此需要将其“分块”

def processChunkFile(chunkfile, outputfile, verbose):
    """
    Processes a given chunk file, looking for XML 1.0 chars.
    Outputs any line containing such a character.
    """
    badlines = []

    if verbose:
        print("Processing file {0}".format(os.path.basename(chunkfile)))

    # open given chunk file and read it as a list of lines
    with open(chunkfile, 'r') as chunk:
        chunklines = chunk.readlines()

        # check to see if a line contains a bad character;
        # if so, add it to the badlines list
        for line in chunklines:
            if badCharacterCheck(line, verbose) == True:
                badlines.append(line)

    # output to file if required
    if outputfile is not None:
        with open(outputfile.encode(), 'a') as outfile:
            for badline in badlines:
                outfile.write(str(badline) + '\n')

    # return list of bad lines
    return badlines



def badCharacterCheck(line, verbose):
    """
    Use regular expressions to seek characters in a line
    which aren't supported in XML 1.0.
    """
    invalidCharacters = re.compile("[^\u0009\u000A\u000D\u0020\u0021-\uD7FF\uE000-\uFFFD\u010000-\u10FFFF]")
    matches = re.search(invalidCharacters, line)
    if matches:
        if verbose:
            print(line)
            print("FOUND: " + matches.groups())
        return True

    return False
呃,怪物XML是痛苦的。但是,使用合理的流式API(和文件系统!)应该仍然可以处理。例如,您可以使用
为块中的行:
一次处理一行,而不是使用
readlines()
一次读取所有块

重新搜索(无效字符,行)

由于
invalidCharacters
已经是一个已编译的模式对象,您可以只
invalidCharacters.search(…)


话虽如此,它仍然与我的U+0007 Bell相匹配。

删除两个已知标记或字符串中两个已知字符之间的单词、字符、字符串或任何内容的最快方法是使用直接的、本机的C方法,使用RE和一个通用的方法,如下所示

var = re.sub('<script>', '<!--', var)
var = re.sub('</script>', '-->', var)
#And finally
var = re.sub('<!--.*?-->', '', var)
var=re.sub(“”,,,var)
#最后
var=re.sub(“”,,,var)
它能去除一切,比漂亮的汤更快、更好、更干净。批处理文件是“”最初出现的地方,只是为了与本机C中的批处理和html一起使用而借用的“。当将所有Pythonic方法与正则表达式一起使用时,您必须意识到Python并没有改变或改变机器语言使用的所有正则表达式,因此,当单个循环可以在一次迭代中找到所有正则表达式时,为什么要重复多次呢?对字符也单独执行相同的操作

var = re.sub('\[', '<!--', var)
var = re.sub('\]', '-->', var)
#And finally
var = re.sub('<!--.*?-->', '' var)#wipes it all out from between along with.
var=re.sub('\[','',var)
#最后
var=re.sub('','var)#从两者之间连同。

而且你不需要漂亮的汤。如果你了解它的工作原理,你也可以使用它们来处理数据。

谢谢bobince-这是许多有用的一般(和具体)建议,我非常感谢。
var = re.sub('\[', '<!--', var)
var = re.sub('\]', '-->', var)
#And finally
var = re.sub('<!--.*?-->', '' var)#wipes it all out from between along with.