質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

4回答

256閲覧

PYTHONの正規表現による置換について

yoshii

総合スコア14

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1グッド

1クリップ

投稿2017/07/22 23:54

###前提・実現したいこと
ここに質問したいことを詳細に書いてください

PYTHON言語、初心者です。><

特定文字列(\t)で始まる行について、
空白で囲まれているか行末の文字列(単語)をすべて{...}でくくりたいと考えているのですが、
正規表現でどう表現したらよいかわからず、こちらに質問させていただきます。

(例)やりたいこと
\t aaa bbb cccc dd eeeeee

\t {aaa} {bbb} {cccc} {dd} {eeeeee}

###発生している問題・エラーメッセージ

正規表現を使って、空白の置換を試みたのですが、 置換対象以外の空白も一緒に置換されてしまい、どう表現したらよいか苦戦しております。。 (例) \t aaa bbb cccc dd eeeeee ↓ 正)\t {aaa} {bbb} {cccc} {dd} {eeeeee} 誤)\t {aaa} {bbb} {cccc} {dd} {eeeeee}

###該当のソースコード

# -*- coding: utf-8 -*- import codecs import re # 対象の文字列 f_in = codecs.open('Sample_in.txt','r','utf-8') f_out = codecs.open('Sample_out.txt','w','utf-8') lines = f_in.readlines() lines2 = [] for line in lines: if line.startswith('\\t'): #\tで始まる行の空白で囲まれているか行末の文字列(単語)をすべて{...}でくくりたい。 #①行末(改行)前に"}"を付与 line = line.replace("\n", "}\n", 1) #②空白始まり文字列を" {"に置換 line = re.sub(r'\s+',r' {',line) #③残りの空白を"} "に置換 line = re.sub(r'\s',r'} ',line) #④誤変換した先頭"}"の削除 line = line.replace("} {", " {", 1) #⑤誤変換した最終文字列に改行を付与 line = line.replace("}} {", "}\n", 1) lines2.append(line) else: f_out.write(''.join(lines2)) f_in.close()

###試したこと
もともとの正規表現は以下を考えておりましたが、正しく変換されず、現在のソースとなっております。
line = re.sub(r'!^| +([ +|$])',r' {\1}\2',line)

###補足情報(言語/FW/ツール等のバージョンなど)
PYTHONのバージョンは、3.6で試しています。

LouiS0616👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

正規表現の部分文字列指定を利用すればシンプルにいけるはず。
問題文の中で書かれている置換がうまくいかないのは、ほおっておけばよいスペースを妙に拾おうしていることと、[]の書き方が間違っていて、行頭とかスペースとかにマッチしないパターンになっているからでしょう。

pythonのプログラムは生まれて初めて書いてみますが、ubuntu/python3.4で試してみた限りでは下のコードでうまくできているように見えます。

python

1# -*- coding: utf-8 -*- 2import codecs 3import re 4 5# 対象の文字列 6f_in = codecs.open('Sample_in.txt','r','utf-8') 7f_out = codecs.open('Sample_out.txt','w','utf-8') 8lines = f_in.readlines() 9lines2 = [] 10for line in lines: 11 if line.startswith('\t'): 12 13 #\tで始まる行の空白で囲まれているか行末の文字列(単語)をすべて{...}でくくりたい。 14 line = re.sub('(\S+)', '{\\1}', line) 15 16 lines2.append(line) 17 18f_out.write(''.join(lines2)) 19f_in.close()

投稿2017/07/23 06:23

KojiDoi

総合スコア13671

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

正規表現とPandas.Seriesを使って、スマートではないですが、できたようなので、検討願います。

Python3

1import re 2import pandas as pd 3lines = ['\t aaa bbb cccc dd eeeeee', '\tAAA BBB C DD EEE'] 4 5# 正規表現を用いて、空白とそれ以外に分離 6st = re.compile('\S+') 7sp = re.compile('\s+') 8for line in lines: 9 if line.startswith('\t'): # \\tは誤り 10 line_st = st.findall(line) # ['aaa', 'bbb', 'cccc', 'dd', 'eeeeee'] 11 line_st = ['{' + str + '}' for str in line_st] # {}追加 12 line_sp = sp.findall(line) # ['\t ', ' ', ' ', ' ', ' '] 13 # line_st:文字、line_sp : 空白 それぞれをシリーズにして、インデックスをいじって結合 14 da = pd.Series(line_sp) 15 da.index = da.index * 2 16 db = pd.Series(line_st) 17 db.index = db.index * 2 + 1 18 c = list(da.append(db).sort_index()) 19 s = ''.join(c) 20 print(s) 21 else: 22 print('Error:',line) # デバック用なので修正願います

投稿2017/07/23 04:33

xxBadMoon2017

総合スコア114

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  • 正規表現で頑張る、という感じではなくなってしまいましたが、、、一応できました。
  • 1行を配列に変換し、前の要素がタブや空白だったら{を追加。
  • 後ろの要素が空白や改行だったら}を追加。
  • 最後に配列を文字列に戻して出来上がり。
import re import codecs pattern = r"^\t+" f_in = codecs.open('sample_in.txt', 'r', 'utf-8') f_out = codecs.open('sample_out.txt', 'w', 'utf-8') lines = f_in.readlines() lines2 = [] for line in lines: if re.match(pattern, line): lineElemList = list(line) for index, elem in enumerate(lineElemList): if lineElemList[index - 1] == '\t' and isinstance(elem, str): new_elem = "{" + elem lineElemList[index] = new_elem elif lineElemList[index - 1] == ' ' and isinstance(elem, str) and elem != ' ': new_elem = "{" + elem lineElemList[index] = new_elem elif index <= len(lineElemList) - 2 and lineElemList[index + 1] == ' ' and isinstance(elem, str) and elem != ' ': new_elem = elem + "}" lineElemList[index] = new_elem elif index == len(lineElemList) - 2 and isinstance(elem, str): new_elem = elem + "}" lineElemList[index] = new_elem newstring = ''.join(lineElemList) lines2.append(newstring) f_out.write(''.join(lines2)) f_in.close()

投稿2017/07/23 04:23

編集2017/07/23 04:31
wakamechan

総合スコア88

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

正規表現でうまく表現できなかったので、状態遷移でコーディングしてみました。
空白 or 文字が出現したタイミングで状態を切り替えて処理しています。

Python

1# 空白はそのまま、文字は{}で囲んで出力 2 3# 'word' -> '{word}' 4def quote( word): 5 if len(word): 6 word = '{' + word + '}' 7 return word 8 9# 'a b' -> '{a} {b}' 10def quoteWords(line): 11 isSpace = True 12 word, line_new = '','' 13 for s in line: 14 if s == ' ': 15 if not isSpace: 16 line_new += quote(word) 17 word = '' 18 line_new += s 19 isSpace = True 20 else: 21 word += s 22 isSpace = False 23 line_new += quote(word) # 空白以外で終わった場合(積み残し) 24 return line_new 25 26lines = ['','a\t','\t','\ta','\ ','\ta ','\t a','\ta b','\t aaa bbb cccc dd eeeeee'] 27for line in lines: 28 if not line.startswith('\t'): 29 continue 30 line = line[1:] # 先頭\t除去 31 line_new = quoteWords(line) 32 33 print('line[%s]'%line) 34 print('line_new[%s]'%line_new)

結果例

line[] line_new[] line[a] line_new[{a}] line[a ] line_new[{a} ] line[ a] line_new[ {a}] line[a b] line_new[{a} {b}] line[ aaa bbb cccc dd eeeeee] line_new[ {aaa} {bbb} {cccc} {dd} {eeeeee}]

投稿2017/07/23 03:49

編集2017/07/23 04:35
can110

総合スコア38258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問