我有一个源UTF8文件(没有BOM,Windows EOL),如下所示:
~someunicodetext_someunicodetext_someunicodetext~
some_more_unicode_text_some_more_unicode_text
~someunicodetext_someunicodetext_someunicodetext~
some_more_unicode_text_some_more_unicode_text
&&even_more_text_here
~someunicodetext_someunicodetext_someunicodetext~
some_more_unicode_text_some_more_unicode_text
~someunicodetext_someunicodetext_someunicodetext~
因此有3种类型的线(如果计算空行则为4种)。我的目标是使用python正则表达式计算每个非空类型。这绝对是使用python 3.x的基于正则表达式的解决方案,因为我想了解它是如何工作的。
我的python脚本看起来像这样:
import re, codecs
pattern = re.compile(r'some_expression_here')
count = 0
with codecs.open("some_input_file", "r", "UTF8") as inputFile:
inputFile=inputFile.read()
lines = re.findall(pattern, inputFile)
for match in lines:
count +=1
print (count)
我遇到的真正问题是实际的正则表达式
~.*~
似乎能够匹配上面示例中的1,4,8等线(如果我们从1开始计算)
&&.*
与第6行匹配
但我无法弄清楚如何计算非标记线,即2,5,9号线
在Notepad ++中,这个表达式^(?!(~.*~)|(&&.*)).*
或者只是这个^(?!~|&).*
对我有用(尽管它不完全正确),但是我在python中复制它的所有尝试都失败了......
修改
inputFile.read()
没有按照我期望的方式读取文件(hello windows EOL)。哪个可能重要,也可能不重要。它的输出如下:
~someunicodetext_someunicodetext_someunicodetext~
some_more_unicode_text_some_more_unicode_text
~someunicodetext_someunicodetext_someunicodetext~
some_more_unicode_text_some_more_unicode_text
&&even_more_text_here
答案 0 :(得分:1)
x="~someunicodetext_someunicodetext_someunicodetext~ \n \n \nsome_more_unicode_text_some_more_unicode_text \n"
pattern=re.compile(r"(\S+)")
print len(pattern.findall(x))
这给出了除space之外的所有行的计数。所以空行不计算。希望这有帮助。
答案 1 :(得分:0)
您可以使用re.MULTILINE标志来尝试此模式^\w.*
。
re.UNICODE
标志也应该用于Python 2。
这是一个完整的例子:
import re, codecs
with codecs.open("input.txt", "r", "UTF8") as inputFile:
data = inputFile.read()
pattern = re.compile(r'^\w.*', flags=re.MULTILINE)
lines = re.findall(pattern, data)
>>> data # note windows line termination
'~someunicodetext_someunicodetext_someunicodetext~\r\nsome_more_unicode_text_some_more_unicode_text\r\n \t\r\n~someunicodetext_someunicodetext_someunicodetext~\r\nsome_more_unicode_text_some_more_unicode_text\r\n&&even_more_text_here\r\n\r\n~someunicodetext_someunicodetext_someunicodetext~\r\nsome_more_unicode_text_some_more_unicode_text\r\n\r\n~someunicodetext_someunicodetext_someunicodetext~\r\n'
>>> print(lines)
['some_more_unicode_text_some_more_unicode_text\r', 'some_more_unicode_text_some_more_unicode_text\r', 'some_more_unicode_text_some_more_unicode_text\r']
>>> print(len(lines))
3
因此正则表达式匹配"未标记的"根据需要使用非空白行。
答案 2 :(得分:0)
这是答案。我仍然不确定我是否正确处理Windows EOL等等,但这似乎是有效的。 另外,我希望有人能够解释我的问题在哪里以及为什么它的工作方式有效,但是很好。
这是做什么的。我们匹配在它之前有~EOL并以另一个EOL结束的每一行。同时,我们确保排除具有2个或更多连续EOL的匹配。
因此。这仅匹配标有〜
的行正下方的行import re, codecs
regex = re.compile(r'(?!~(\r\n){2,})~\r\n.*\r\n', re.MULTILINE)
count = 0
with codecs.open('input_file', 'r', 'UTF8') as inputFile:
inputFile=inputFile.read()
lines = re.findall(regex, inputFile)
for match in lines:
count +=1
print (count)
答案 3 :(得分:0)
"未标记"可以将行标识为不是并且不以~
开头且不以&
开头的行。< / p>
因此以下正则表达式将起作用:
^[^&\s].*
阅读:^
=开头匹配,[^...]
=一个不在的单个字符,&\s
= charchter &
或空白字符(即不其中之一),.*
=之后可以有任何事情发生。
(我放入\s
以防万一,因为你说你遇到了换行问题。我不确定是否需要它。
此外,逐行读取文件要好得多。你得到:
import re, codecs
pattern = re.compile(r'^[^&\s].*')
with codecs.open("some_input_file", "r", "UTF8") as inputFile:
count = sum( 1 for line in inputFile if re.search(pattern, line) )
print (count)