#python #regex #replace
#python #Регулярное выражение #заменить
Вопрос:
Мне нужно выполнить поиск регулярных выражений и заменить все запятые, найденные внутри блоков кавычек.
т.е.
"thing1,blah","thing2,blah","thing3,blah",thing4
необходимо стать
"thing1,blah","thing2,blah","thing3,blah",thing4
мой код:
inFile = open(inFileName,'r')
inFileRl = inFile.readlines()
inFile.close()
p = re.compile(r'["]([^"]*)["]')
for line in inFileRl:
pg = p.search(line)
# found comment block
if pg:
q = re.compile(r'[^\],')
# found comma within comment block
qg = q.search(pg.group(0))
if qg:
# Here I want to reconstitute the line and print it with the replaced text
#print re.sub(r'([^\]),',r'1,',pg.group(0))
Мне нужно отфильтровать только те столбцы, которые я хочу, на основе регулярного выражения, отфильтровать дальше,
затем выполнить замену регулярного выражения, а затем восстановить строку обратно.
Как я могу это сделать на Python?
Комментарии:
1. на самом деле это не ответ, но, прежде чем вы его переопределите, может быть, вам лучше подойдет анализатор CSV? Похоже, это формат, с которым вы имеете дело.
2. На самом деле я хочу подготовить данные для моего пользовательского анализатора CSV csv.register_dialect(‘escapedExcel’ , delimiter = ‘,’ , skipinitialspace = 0 , doublequote = 1 , quoting = csv. QUOTE_ALL , quotechar = ‘»‘ , lineterminator = ‘r n’ , escapechar = ‘\’ )
3. Я понимаю, тогда я полагаю, что вы хотите использовать методы
span
иstart
объекта match, чтобы получить доступ к тому, что было вокруг него, и перекомпилировать свою строку. Но я не уверен, почему один вызов sub после цикла «выбора» не будет в порядке.4. @Dragos Toader: Почему вы хотите заменить запятые внутри кавычек?
csv.reader
не имеет проблем с запятыми внутри кавычек.5. Добавление обратной косой черты просто означает еще один механизм, с которым должен справиться ваш анализатор. Теперь вам также нужно будет использовать обратную косую черту для всех обратных косых черт. Правильное решение — научить ваш анализатор CSV игнорировать запятые внутри двойных кавычек или использовать существующий анализатор CSV, который это делает.
Ответ №1:
csv
Модуль идеально подходит для анализа данных, подобных этому, поскольку csv.reader
в диалекте по умолчанию игнорируются кавычки с запятыми. csv.writer
повторно вставляет кавычки из-за наличия запятых. Раньше я StringIO
предоставлял файлоподобный интерфейс для строки.
import csv
import StringIO
s = '''"thing1,blah","thing2,blah","thing3,blah"
"thing4,blah","thing5,blah","thing6,blah"'''
source = StringIO.StringIO(s)
dest = StringIO.StringIO()
rdr = csv.reader(source)
wtr = csv.writer(dest)
for row in rdr:
wtr.writerow([item.replace('\,',',').replace(',','\,') for item in row])
print dest.getvalue()
Результат:
"thing1,blah","thing2,blah","thing3,blah"
"thing4,blah","thing5,blah","thing6,blah"
Комментарии:
1. 1 Но вам нужно написать
item.replace('\,',',').replace(',','\,')
, иначе «thing3 , бла» заменяется на «thing3 \, бла»
Ответ №2:
Общее редактирование
Там было
"thing1\,blah","thing2\,blah","thing3\,blah",thing4
в вопросе, и теперь его там больше нет.
Более того, я не заметил r'[^\],'
.
Итак, я полностью переписываю свой ответ.
"thing1,blah","thing2,blah","thing3,blah",thing4
и
"thing1,blah","thing2,blah","thing3,blah",thing4
отображение строк (я полагаю)
import re
ss = '"thing1,blah","thing2,blah","thing3,blah",thing4 '
regx = re.compile('"[^"]*"')
def repl(mat, ri = re.compile('(?<!\\),') ):
return ri.sub('\\',mat.group())
print ss
print repr(ss)
print
print regx.sub(repl, ss)
print repr(regx.sub(repl, ss))
Результат
"thing1,blah","thing2,blah","thing3,blah",thing4
'"thing1,blah","thing2,blah","thing3\,blah",thing4 '
"thing1blah","thing2blah","thing3,blah",thing4
'"thing1\blah","thing2\blah","thing3\,blah",thing4 '
Комментарии:
1. Этот ответ был отклонен. Я хотел бы знать, почему. Я также озадачен тем фактом, что моя репутация затем уменьшается на 1, а не на 2 балла!
Ответ №3:
Вы можете попробовать это регулярное выражение.
>>> re.sub('(?<!"),(?!")', r"\,",
'"thing1,blah","thing2,blah","thing3,blah",thing4')
#Gives "thing1,blah","thing2,blah","thing3,blah",thing4
Логика, лежащая в основе этого, заключается в замене a ,
на ,
, если ему не предшествует и не следует сразу a "
Комментарии:
1. Ваше решение лучше моего. Вам просто нужно написать шаблон
'([^"] ) *, *([^"] )'
или даже'([^"] )[t ]*,[t ]*([^"] )'
в случае, если между пробелами стоит запятая2. Добавлены проверки, о которых вы упомянули. Спасибо!
3. Как это работает со строками с двумя запятыми между кавычками?
"thing1,blah,moreblah"
4. @StevenRumbalski Да, в этом случае это не сработает. В этом сценарии должны использоваться как lookahead, так и lookbehind. Я посмотрю, смогу ли я внести эти изменения.
5. Как насчет
re.sub('". ?"', lambda m: m.group(0).replace(',','\,'), '"th,ing1,blah","thing2,""blah""","thing3,blah",thing4')
?
Ответ №4:
Я придумал итеративное решение, используя несколько функций регулярных выражений:
finditer(), findall(), group(), start() и end()
Есть способ превратить все это в рекурсивную функцию, которая вызывает саму себя.
Есть желающие?
outfile = open(outfileName,'w')
p = re.compile(r'["]([^"]*)["]')
q = re.compile(r'([^\])(,)')
for line in outfileRl:
pg = p.finditer(line)
pglen = len(p.findall(line))
if pglen > 0:
mpgstart = 0;
mpgend = 0;
for i,mpg in enumerate(pg):
if i == 0:
outfile.write(line[:mpg.start()])
qg = q.finditer(mpg.group(0))
qglen = len(q.findall(mpg.group(0)))
if i > 0 and i < pglen:
outfile.write(line[mpgend:mpg.start()])
if qglen > 0:
for j,mqg in enumerate(qg):
if j == 0:
outfile.write( mpg.group(0)[:mqg.start()] )
outfile.write( re.sub(r'([^\])(,)',r'1\2',mqg.group(0)) )
if j == (qglen-1):
outfile.write( mpg.group(0)[mqg.end():] )
else:
outfile.write(mpg.group(0))
if i == (pglen-1):
outfile.write(line[mpg.end():])
mpgstart = mpg.start()
mpgend = mpg.end()
else:
outfile.write(line)
outfile.close()
Комментарии:
1. Ваш код невероятно извилист: вы используете регулярные выражения для выполнения лишь небольшой части того, для чего предназначены регулярные выражения, чтобы получить элементы строки, с которыми вы выполняете обработку, благодаря строковым методам, которые являются именно тем, что делается с регулярными выражениями. Кстати, вы не заметили, что ваш код выдает ложный результат для «thing3, blah» , который преобразуется в «thingx x03, blah» , я не знаю как.
2. Кроме того, кстати, вы в какой-то момент заметили, что были ответы и дебаты относительно вопроса, который вы точно задали, чтобы получить ответы? Вы не делаете ни малейшего намека на другие ответы, которые, как мы надеялись, были полезны. Вместо этого вы показываете код без какого-либо интереса, как будто вы не читали ответы. Я нахожу это немного несправедливым.
Ответ №5:
вы изучали str.replace()?
str.replace(старый, новый [, количество]) Возвращает копию строки со всеми вхождениями старой подстроки, замененной новой. Если задан необязательный аргумент count , заменяются только первые вхождения count.
вот некоторая документация
надеюсь, это поможет