Подтвердить что ты не робот

Python: строка, которая не начинается С#

У меня есть файл, который содержит что-то вроде

# комментарий
# комментарий
 не комментарий

# комментарий
# комментарий
 не комментарий

Я пытаюсь прочитать файл строки за строкой и только фиксировать строки, которые не начинаются С#. Что не так с моим кодом/регулярным выражением?

import re

def read_file():
    pattern = re.compile("^(?<!# ).*")

    with open('list') as f:
        for line in f:
            print pattern.findall(line)

Исходный код захватывает все, а не ожидаемое.

4b9b3361

Ответ 1

Альтернативный и все же простой подход состоит в том, чтобы проверить, не содержит ли первый char каждой прочитанной строки # символ:

def read_file():

    with open('list') as f:
        for line in f:
            if not line.lstrip().startswith('#'):
                print line

Ответ 2

Iron Fist показывает, как вы, вероятно, должны это сделать; однако, если вы хотите знать, что было не так с вашим регулярным выражением, это должно быть так:

^[^#].*

Пояснение:

  • ^ - соответствует началу строки.
  • [^#] - сопоставить то, что не является #. [^...] заключается в том, как вы говорите, что не что-то сопоставить (просто замените ... на любые символы, которые вы не хотите сопоставлять. Например, [^ABC123] будет соответствовать символу, который не является ни одним из A, B, C, 1, 2, или 3. Не допускайте, чтобы ^, указывающий начало строки/строки, вас путают. Эти два ^ полностью не связаны.
  • .* - сопоставить ноль или больше всего.

EDIT:

Причина ^(?<!# ).* НЕ различает # comment, а not a comment заключается в том, что (?<!#) проверяет текст перед текущей позицией. Двигатель ищет # перед первым символом после начала строки, а поскольку перед началом строки нет #, любая строка соответствует подшаблону .*. Чтобы действительно проверить, является ли первый символ #, вам просто нужно использовать ^#.* regex. Или, если могут быть ведущие пробелы, ^\s*#.

Ответ 3

Потому что:

(?!# ) Отрицательный Lookahead. Подтвердите, что соответствие регулярному выражению ниже. (?<!# ) Отрицательный Lookbehind. Убедитесь, что невозможно совместить регулярное выражение #.
, который из regex101

Это означает, что за этим стоит только #. Итак, я имею в виду:

>>> re.search('foo(?!bar)', 'foobar')
>>> re.search('foo(?<!bar)', 'foobar')  # doesn't work
<_sre.SRE_Match object; span=(0, 3), match='foo'>


>>> re.search('(?<!bar)foo', 'barfoo')
>>> re.search('(?!bar)foo', 'barfoo')   # doesn't work
<_sre.SRE_Match object; span=(3, 6), match='foo'>

Это потому, что вы использовали неправильный токен. Поэтому ответ очень прост:

Используйте (?!bar), если вы не хотите строку после bar.
Используйте (?<!bar), если вы не хотите какой-либо строки перед bar.

Ответ 4

В этом случае используйте функцию match, так как она будет проверяться в начале.

Таким образом, выражение будет \s*[^#] - для удобства я использую \s для пропуска пробелов.

Код OP будет -

def read_file():
    pattern = re.compile("\s*[^#]")
    with open(r"C:\test.txt") as f:
        for line in f:
            if pattern.match(line):
                    print line
read_file()

ИЗМЕНИТЬ -

Немного объяснения, почему шаблон OP не работает -

При использовании . это означает все, кроме символа прерывания строки. Поэтому, когда вы пишете ^(?<!# ).*, это означает символ any (кроме строки break-include включает # damn it!), Который раньше не был # - в конце концов он становится любой строкой (кроме варианта разрыва строки) начинается с any.

См. LIVE DEMO

Решение:

Попробуйте negation как ^(?<!# )[^#]