Como inserir um regex em string.replace?

317

Preciso de ajuda para declarar uma regex. Minhas entradas são como as seguintes:

this is a paragraph with<[1> in between</[1> and then there are cases ... where the<[99> number ranges from 1-100</[99>. 
and there are many other lines in the txt files
with<[3> such tags </[3>

A saída necessária é:

this is a paragraph with in between and then there are cases ... where the number ranges from 1-100. 
and there are many other lines in the txt files
with such tags

Eu tentei isso:

#!/usr/bin/python
import os, sys, re, glob
for infile in glob.glob(os.path.join(os.getcwd(), '*.txt')):
    for line in reader: 
        line2 = line.replace('<[1> ', '')
        line = line2.replace('</[1> ', '')
        line2 = line.replace('<[1>', '')
        line = line2.replace('</[1>', '')

        print line

Eu também tentei isso (mas parece que estou usando a sintaxe regex errada):

    line2 = line.replace('<[*> ', '')
    line = line2.replace('</[*> ', '')
    line2 = line.replace('<[*>', '')
    line = line2.replace('</[*>', '')

Não quero codificar replacede 1 a 99. . .

alvas
fonte
4
A resposta aceita já cobre o seu problema e resolve-o. Você precisa de mais alguma coisa ?
Hamza
Qual deve ser o resultado where the<[99> number ranges from 1-100</[100>?
utapyngo
ele também deve remover o número da <...>tag, então a saída deve serwhere the number rangers from 1-100 ?
alvas

Respostas:

566

Este snippet testado deve fazer isso:

import re
line = re.sub(r"</?\[\d+>", "", line)

Edit: Aqui está uma versão comentada explicando como funciona:

line = re.sub(r"""
  (?x) # Use free-spacing mode.
  <    # Match a literal '<'
  /?   # Optionally match a '/'
  \[   # Match a literal '['
  \d+  # Match one or more digits
  >    # Match a literal '>'
  """, "", line)

Regexes são divertidos! Mas eu recomendaria fortemente passar uma ou duas horas estudando o básico. Para iniciantes, você precisa aprender quais personagens são especiais: "metacaracteres" que precisam ser escapados (ou seja, com uma barra invertida colocada na frente - e as regras são diferentes dentro e fora das classes de personagens). Existe um excelente tutorial on-line em: www .regular-expression.info . O tempo que você passa lá se paga muitas vezes. Feliz regexing!

ridgerunner
fonte
sim funciona !! obrigado, mas você pode explicar o regex em breve?
alvas
9
Também não negligenciar O Livro sobre Expressões Regulares - Dominando Expressões Regulares , por Jeffrey Friedl
pcurry
Outra boa referência vê w3schools.com/python/python_regex.asp
Carson
38

str.replace()faz substituições fixas. Use em re.sub()vez disso.

Ignacio Vazquez-Abrams
fonte
3
Também é importante notar que seu padrão deve ser algo como "</ {0-1} \ d {1-2}>" ou qualquer outra variante da notação regexp usada pelo python.
3
O que significa substituições fixas?
avi
@avi Provavelmente ele quis dizer substituição de palavras fixa, localização parcial de palavras através de regex.
Gunay Anach
cadeias fixas (literais, constantes)
vstepaniuk 31/07/19
23

Eu iria assim (regex explicado nos comentários):

import re

# If you need to use the regex more than once it is suggested to compile it.
pattern = re.compile(r"</{0,}\[\d+>")

# <\/{0,}\[\d+>
# 
# Match the character “<” literally «<»
# Match the character “/” literally «\/{0,}»
#    Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «{0,}»
# Match the character “[” literally «\[»
# Match a single digit 0..9 «\d+»
#    Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
# Match the character “>” literally «>»

subject = """this is a paragraph with<[1> in between</[1> and then there are cases ... where the<[99> number ranges from 1-100</[99>. 
and there are many other lines in the txt files
with<[3> such tags </[3>"""

result = pattern.sub("", subject)

print(result)

Se você quiser saber mais sobre o regex, recomendo ler o Regular Expressions Cookbook de Jan Goyvaerts e Steven Levithan.

Lorenzo Persichetti
fonte
2
Você poderia simplesmente usar *em vez de{0,}
Hamza
3
Nos documentos python : {0,}é o mesmo que *, {1,}é equivalente a +e {0,1}é o mesmo que ?. É melhor usar *, +ou ?quando puder, simplesmente porque são mais curtos e fáceis de ler.
winklerrr
15

A maneira mais fácil

import re

txt='this is a paragraph with<[1> in between</[1> and then there are cases ... where the<[99> number ranges from 1-100</[99>.  and there are many other lines in the txt files with<[3> such tags </[3>'

out = re.sub("(<[^>]+>)", '', txt)
print out
Ezequiel Marquez
fonte
Os parênteses são realmente necessários? Não seria o mesmo regex <[^>]+>:? A propósito: Eu acho que sua regex combinaria muito (por exemplo, algo como <html>)
winklerrr
10

O método replace de objetos de seqüência de caracteres não aceita expressões regulares, mas apenas seqüências de caracteres fixas (consulte a documentação: http://docs.python.org/2/library/stdtypes.html#str.replace ).

Você precisa usar o remódulo:

import re
newline= re.sub("<\/?\[[0-9]+>", "", line)
Zac
fonte
4
Você deve usar em \d+vez de[0-9]+
winklerrr
3

não precisa usar expressão regular (para sua sequência de amostra)

>>> s
'this is a paragraph with<[1> in between</[1> and then there are cases ... where the<[99> number ranges from 1-100</[99>. \nand there are many other lines in the txt files\nwith<[3> such tags </[3>\n'

>>> for w in s.split(">"):
...   if "<" in w:
...      print w.split("<")[0]
...
this is a paragraph with
 in between
 and then there are cases ... where the
 number ranges from 1-100
.
and there are many other lines in the txt files
with
 such tags
Kurumi
fonte
3
import os, sys, re, glob

pattern = re.compile(r"\<\[\d\>")
replacementStringMatchesPattern = "<[1>"

for infile in glob.glob(os.path.join(os.getcwd(), '*.txt')):
   for line in reader: 
      retline =  pattern.sub(replacementStringMatchesPattern, "", line)         
      sys.stdout.write(retline)
      print (retline)
Abena Saulka
fonte