PythonのPerlのchomp
関数とは何ですか?これは文字列の最後の文字が改行であればそれを削除しますか?
メソッドrstrip()
を試してください(doc Python 2 および Python 3 を参照)
>>> 'test string\n'.rstrip()
'test string'
Pythonのrstrip()
メソッドは、デフォルトで all のような末尾の空白を取り除きます。Perlが chomp
のように改行を1つだけではありません。
>>> 'test string \n \r\n\n\r \n\n'.rstrip()
'test string'
改行だけを削除するには:
>>> 'test string \n \r\n\n\r \n\n'.rstrip('\n')
'test string \n \r\n\n\r '
メソッドlstrip()
とstrip()
もあります。
>>> s = " \n\r\n \n abc def \n\r\n \n "
>>> s.strip()
'abc def'
>>> s.lstrip()
'abc def \n\r\n \n '
>>> s.rstrip()
' \n\r\n \n abc def'
改行文字を付けずに行を取得する "Pythonic"の方法はsplitlines()です.
>>> text = "line 1\nline 2\r\nline 3\nline 4"
>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']
行末(EOL)文字を取り除く標準的な方法は、文字列rstrip()メソッドを使用して末尾の\ rまたは\ nを削除することです。これは、Mac、Windows、およびUnixのEOL文字の例です。
>>> 'Mac EOL\r'.rstrip('\r\n')
'Mac EOL'
>>> 'Windows EOL\r\n'.rstrip('\r\n')
'Windows EOL'
>>> 'Unix EOL\n'.rstrip('\r\n')
'Unix EOL'
Rstripのパラメータとして '\ r\n'を使用すると、末尾の '\ r'または '\ n'の組み合わせはすべて削除されます。だからこそ、上記の3つのケースすべてでうまくいくのです。
この微妙なニュアンスはまれに発生します。たとえば、HL7メッセージを含むテキストファイルを処理しなければなりませんでした。 HL7規格では、EOL文字として末尾の '\ r'が必要です。このメッセージを使用していたWindowsマシンには、独自の '\ r\n' EOL文字が付加されていました。したがって、各行の終わりは '\ r\r\n'のように見えました。 rstrip( '\ r\n')を使用すると '\ r\r\n'全体が削除されますが、これは私が望んでいたことではありません。その場合は、最後の2文字を単純にスライスしました。
Perlのchomp
関数とは異なり、これは1つだけではなく、文字列の最後に指定されたすべての文字を削除します。
>>> "Hello\n\n\n".rstrip("\n")
"Hello"
Rstripは、文字列を変更しないため、Perlのchomp()とまったく同じようには動作しません。つまり、Perlでは、
$x="a\n";
chomp $x
$x
は"a"
になります。
しかし、Pythonでは:
x="a\n"
x.rstrip()
x
の値が still "a\n"
であることを意味します。たとえx=x.rstrip()
でも、同じ結果になるとは限りません。それは、たった1行の改行ではなく、文字列の末尾からすべての空白を削除するからです。
私はこのようなものを使うかもしれません:
import os
s = s.rstrip(os.linesep)
rstrip("\n")
の問題は、おそらく行区切り文字が移植可能であることを確認したいということでしょう。 (時代遅れのシステムでは"\r\n"
を使うと噂されている)もう1つの問題は、rstrip
が繰り返し空白を削除することです。うまくいけばos.linesep
は正しい文字を含みます。上記は私のために働きます。
line = line.rstrip('\n')
を使うことができます。これは1つだけでなく、文字列の末尾からすべての改行を取り除きます。
s = s.rstrip()
文字列s
の末尾にあるすべての改行を削除します。 rstrip
は元の文字列を変更する代わりに新しい文字列を返すので、割り当てが必要です。
"line 1\nline 2\r\n...".replace('\n', '').replace('\r', '')
>>> 'line 1line 2...'
それとも、あなたはいつも正規表現でオタクになることができます:)
楽しむ!
これはPerlのchomp(配列上の振る舞いを除く)を "\ n"の行末記号として正確に複製します。
def chomp(x):
if x.endswith("\r\n"): return x[:-2]
if x.endswith("\n") or x.endswith("\r"): return x[:-1]
return x
(注:文字列の「その場で」は変更されません。末尾の余分な空白は削除されません。
あなたはストリップを使用することができます:
line = line.strip()
デモ:
>>> "\n\n hello world \n\n".strip()
'hello world'
"foo".rstrip(os.linesep)
に気をつけて:Pythonが実行されているプラットフォームの改行文字だけを切り捨てます。たとえば、LinuxでWindowsファイルの行をチッピングしていると想像してみてください。
$ python
Python 2.7.1 (r271:86832, Mar 18 2011, 09:09:48)
[GCC 4.5.0 20100604 [gcc-4_5-branch revision 160292]] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, sys
>>> sys.platform
'linux2'
>>> "foo\r\n".rstrip(os.linesep)
'foo\r'
>>>
マイクが上記のように、代わりに"foo".rstrip("\r\n")
を使用してください。
Pythonのドキュメントの の例 は単にline.strip()
を使っています。
Perlのchomp
関数は、それが実際にそこにある場合にのみ、文字列の末尾から1つの改行シーケンスを削除します。
process
が概念的にこのファイルの各行に役立つ何かをするために必要な関数であるならば、私がPythonでそれをどのようにするつもりであるかは以下の通りです:
import os
sep_pos = -len(os.linesep)
with open("file.txt") as f:
for line in f:
if line[sep_pos:] == os.linesep:
line = line[:sep_pos]
process(line)
rstripはchompと同じことを、多くのレベルでは行いません。 http://perldoc.Perl.org/functions/chomp.html を読んで、chompが実際には非常に複雑であることを確認してください。
しかし、私の主な点は、chompが最大で1行の終わりまでを削除するのに対して、rstripはできるだけ多くの行を削除することです。
ここでは、rstripがすべての改行を削除しているのがわかります。
>>> 'foo\n\n'.rstrip(os.linesep)
'foo'
次のように、典型的なPerlのchompの使用法をはるかに近似したものをre.subで実現することができます。
>>> re.sub(os.linesep + r'\Z','','foo\n\n')
'foo\n'
私はPythonでプログラムしませんが、python.orgで _ faq _ に出会いました。
import re
r_unwanted = re.compile("[\n\t\r]")
r_unwanted.sub("", your_text)
複数行のstrオブジェクト(oldstr)のすべての改行をクリーンアップすることが問題である場合は、区切り文字 '\ n'に従ってリストに分割してから、このリストを新しいstr(newstr)に結合することができます。
newstr = "".join(oldstr.split('\n'))
特別な場合の回避策
改行文字が最後の文字である場合(ほとんどのファイル入力の場合のように)、コレクション内の任意の要素に対して、次のようにインデックスを付けることができます。
foobar= foobar[:-1]
改行文字を切り捨てます。
以前に別の回答のコメントで投稿したものからの正規表現ベースの回答をバブリングしています。 re
を使用することは、str.rstrip
よりもこの問題に対するより明確な解決策だと思います。
>>> import re
1つ以上のtrailing改行文字を削除する場合:
>>> re.sub(r'[\n\r]+$', '', '\nx\r\n')
'\nx'
(末尾だけでなく)どこでも改行文字を削除したい場合:
>>> re.sub(r'[\n\r]+', '', '\nx\r\n')
'x'
1-2個の末尾の改行文字(つまり、\r
、\n
、\r\n
、\n\r
、\r\r
、\n\n
)のみを削除する場合
>>> re.sub(r'[\n\r]{1,2}$', '', '\nx\r\n\r\n')
'\nx\r'
>>> re.sub(r'[\n\r]{1,2}$', '', '\nx\r\n\r')
'\nx\r'
>>> re.sub(r'[\n\r]{1,2}$', '', '\nx\r\n')
'\nx'
ここでほとんどの人が本当に望んでいるのは、後続の改行文字(\r\n
または\n
のいずれか)の発生のみoneを削除することです。
>>> re.sub(r'(?:\r\n|\n)$', '', '\nx\n\n', count=1)
'\nx\n'
>>> re.sub(r'(?:\r\n|\n)$', '', '\nx\r\n\r\n', count=1)
'\nx\r\n'
>>> re.sub(r'(?:\r\n|\n)$', '', '\nx\r\n', count=1)
'\nx'
>>> re.sub(r'(?:\r\n|\n)$', '', '\nx\n', count=1)
'\nx'
(?:
は、非キャプチャグループを作成することです。)
(ちなみに、これはnotこのスレッドにつまずく他の人には明らかではないかもしれない'...'.rstrip('\n', '').rstrip('\r', '')
の動作です。str.rstrip
は、末尾の文字を可能な限り削除するため、foo\n\n\n
のような文字列では、foo
の誤検知が発生しますが、単一の末尾の改行を削除した後、他の改行を保持することもできます。
Perlの chomp に完全に類似したものがないようです。特に、 rstrip は、\r\n
のような複数文字の改行区切り文字を処理できません。しかし、 splitlines does ここで指摘するように 。 私の答え /別の質問では、 join と splitlines を組み合わせて削除できます文字列s
からのすべての改行を置き換えます。
''.join(s.splitlines())
以下は正確に1つの 末尾newlineを削除します(chompがそうであるように、私は信じています)。 splitlineにTrue
引数としてkeepends
を渡すと、区切り文字が保持されます。その後、splitlinesが再度呼び出されて、最後の "line"の区切り文字が削除されます。
def chomp(s):
if len(s):
lines = s.splitlines(True)
last = lines.pop()
return ''.join(lines + last.splitlines())
else:
return ''
ファイルオブジェクトからチャンプされていない行を取得するのと同じ方法で、イテレータでチャンプされた行を取得できると便利です。次のコードでそれを行うことができます。
def chomped_lines(it):
return map(operator.methodcaller('rstrip', '\r\n'), it)
使用例
with open("file.txt") as infile:
for line in chomped_lines(infile):
process(line)
>>> ' spacious '.rstrip()
' spacious'
>>> "AABAA".rstrip("A")
'AAB'
>>> "ABBA".rstrip("AB") # both AB and BA are stripped
''
>>> "ABCABBA".rstrip("AB")
'ABC'
ただ使用してください:
line = line.rstrip("\n")
または
line = line.strip("\n")
このような複雑なものは必要ありません。
私達が通常遭遇する3つのタイプの行末があります:\n
、\r
および\r\n
。 re.sub
のかなり単純な正規表現、つまりr"\r?\n?$"
は、それらすべてを捉えることができます。
(そして私たちはすべてを捕まえた、そうですか?)
import re
re.sub(r"\r?\n?$", "", the_text, 1)
最後の議論では、chompをある程度模倣しながら、置き換えられるオカレンスの数を1つに制限します。例:
import re
text_1 = "hellothere\n\n\n"
text_2 = "hellothere\n\n\r"
text_3 = "hellothere\n\n\r\n"
a = re.sub(r"\r?\n?$", "", text_1, 1)
b = re.sub(r"\r?\n?$", "", text_2, 1)
c = re.sub(r"\r?\n?$", "", text_3, 1)
... a == b == c
はTrue
です。
もしあなたがスピードを気にしていて(例えば、あなたが文字列のリストをたくさん持っていると言って)改行文字の性質を知っているなら、文字列スライスは実際にはrstripより速いです。これを説明するためのちょっとしたテスト:
import time
loops = 50000000
def method1(loops=loops):
test_string = 'num\n'
t0 = time.time()
for num in xrange(loops):
out_sting = test_string[:-1]
t1 = time.time()
print('Method 1: ' + str(t1 - t0))
def method2(loops=loops):
test_string = 'num\n'
t0 = time.time()
for num in xrange(loops):
out_sting = test_string.rstrip()
t1 = time.time()
print('Method 2: ' + str(t1 - t0))
method1()
method2()
出力:
Method 1: 3.92700004578
Method 2: 6.73000001907
これはwindowsとlinuxの両方でうまくいくでしょう(あなたが唯一の解決策を探しているならre subで少し高価です)
import re
if re.search("(\\r|)\\n$", line):
line = re.sub("(\\r|)\\n$", "", line)