chomp
Bir dizgenin yeni satırsa son karakterini kaldıran Perl işlevinin Python eşdeğeri nedir ?
open()
uygun 'newline = ...' parametresine (evrensel newline desteği) sahip bir dosyayı unutması nedeniyle açık bir şekilde kaldırmanız gerekmeyebilir.
chomp
Bir dizgenin yeni satırsa son karakterini kaldıran Perl işlevinin Python eşdeğeri nedir ?
open()
uygun 'newline = ...' parametresine (evrensel newline desteği) sahip bir dosyayı unutması nedeniyle açık bir şekilde kaldırmanız gerekmeyebilir.
Yanıtlar:
Yöntemi deneyin rstrip()
(bkz. Doc Python 2 ve Python 3 )
>>> 'test string\n'.rstrip()
'test string'
Python'un rstrip()
yöntemi , Perl'in yaptığı gibi sadece bir satırsonu değil, varsayılan olarak her türlü sondaki boşlukları ayırır chomp
.
>>> 'test string \n \r\n\n\r \n\n'.rstrip()
'test string'
Yalnızca yeni satırları ayırmak için:
>>> 'test string \n \r\n\n\r \n\n'.rstrip('\n')
'test string \n \r\n\n\r '
Ayrıca yöntemler lstrip()
ve 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'
\n
Unix gibi yeni satırlar için kullanır . (OS X'ten önce MacOS, \r
hat ayırıcı olarak kullanıyordu , ancak bu 10 yıl önce sona erdi.)
.strip()
dizeyi değiştirmez (muhtemelen değişmez dizelerle ilgisi vardır). Komut satırında değilse, isteyeceksiniz"string = string.strip()"
Ve yeni satır karakterlerini izlemeden satır almanın "pythonic" yolunun splitlines () olduğunu söyleyebilirim.
>>> text = "line 1\nline 2\r\nline 3\nline 4"
>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']
Satır sonu (EOL) karakterlerini ayırmanın kurallı yolu, izleyen \ r veya \ n dizesini kaldırmak için string rstrip () yöntemini kullanmaktır. Aşağıda Mac, Windows ve Unix EOL karakterlerine örnekler verilmiştir.
>>> '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 parametresi olarak '\ r \ n' kullanılması, herhangi bir '\ r' veya '\ n' kombinasyonunu kaldırması anlamına gelir. Bu yüzden yukarıdaki üç durumda da çalışır.
Bu nüans nadir durumlarda önemlidir. Örneğin, bir zamanlar bir HL7 mesajı içeren bir metin dosyasını işlemek zorunda kaldım. HL7 standardı, EOL karakteri olarak bir "r" gerektirir. Bu iletiyi kullandığım Windows makinesi kendi '\ r \ n' EOL karakterini eklemişti. Bu nedenle, her satırın sonu '\ r \ r \ n' gibi görünüyordu. Rstrip ('\ r \ n') kullanmak istediğim gibi olmayan tüm '\ r \ r \ n' kodunu çıkarırdı. Bu durumda, sadece son iki karakteri dilimledim.
Perl chomp
işlevinden farklı olarak , bunun yalnızca bir değil, dizenin sonunda belirtilen tüm karakterleri sileceğini unutmayın:
>>> "Hello\n\n\n".rstrip("\n")
"Hello"
os.linesep
Mevcut işletim sistemi için EOL dizisini içeren de vardır .
\n
ve\r
Dizgeyi değiştirmediği için rstrip komutunun Perl chomp () işlevi görmediğini unutmayın. Yani, Perl'de:
$x="a\n";
chomp $x
sonuçlanır $x
olmak "a"
.
ama Python'da:
x="a\n"
x.rstrip()
değerinin halax
olduğu anlamına gelir . Hatta her zaman aynı sonucu vermez, çünkü en fazla bir satırsonu değil, tüm boşlukları dizenin sonundan ayırır. "a\n"
x=x.rstrip()
Ben böyle bir şey kullanabilirsiniz:
import os
s = s.rstrip(os.linesep)
Bence sorun rstrip("\n")
muhtemelen çizgi ayırıcı taşınabilir olduğundan emin olmak isteyeceksiniz. (bazı eski sistemlerin kullanıldığı söyleniyor "\r\n"
). Diğer sorun ise rstrip
tekrarlanan boşlukları çıkaracak. Umarım os.linesep
doğru karakterleri içerir. yukarıdakiler benim için çalışıyor.
rstrip('\r\n')
ve rstrip()
şerit olacak.
Bu, "\ n" satır sonlandırıcısı için perl kodunu (dizilerde eksi davranış) tam olarak çoğaltır:
def chomp(x):
if x.endswith("\r\n"): return x[:-2]
if x.endswith("\n") or x.endswith("\r"): return x[:-1]
return x
(Not: 'yerinde' dizesini değiştirmez; fazladan boşluk bırakmaz; \ r \ n dikkate alır)
"line 1\nline 2\r\n...".replace('\n', '').replace('\r', '')
>>> 'line 1line 2...'
ya da her zaman regexps ile geekier alabilirsiniz :)
iyi eğlenceler!
.replace('\n|\r', '')
?
import re
re.sub('\n|\r', '', '\nx\n\r\n')
==> 'x'
.
şerit kullanabilirsiniz:
line = line.strip()
demo:
>>> "\n\n hello world \n\n".strip()
'hello world'
rstrip pek çok seviyede chomp ile aynı şeyi yapmaz. Http://perldoc.perl.org/functions/chomp.html adresini okuyun ve chomp'ın gerçekten çok karmaşık olduğunu görün.
Ancak, asıl amacım chomp en fazla 1 satır sonunu kaldırırken, rstrip olabildiğince fazla kaldıracaktır.
Burada rstrip'in tüm yeni satırları kaldırdığını görebilirsiniz:
>>> 'foo\n\n'.rstrip(os.linesep)
'foo'
Re.sub ile tipik Perl pirzolası kullanımının çok daha yakın bir şekilde gerçekleştirilmesi mümkündür, örneğin:
>>> re.sub(os.linesep + r'\Z','','foo\n\n')
'foo\n'
Dikkatli olun "foo".rstrip(os.linesep)
: Bu yalnızca Python'unuzun yürütüldüğü platform için yeni satır karakterlerini chomp eder. Linux altında bir Windows dosyasının satırlarını şımarttığınızı düşünün, örneğin:
$ 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")
Bunun yerine Mike'ın yukarıda söylediği gibi kullanın .
chomp
.
Python'un belgelerindeki bir örnek sadece kullanır line.strip()
.
Perl chomp
işlevi, bir satır sonu dizisini yalnızca gerçekten varsa bir dizenin sonundan kaldırır.
Python, bunu process
kavramsal olarak bu dosyadan her satır için yararlı bir şey yapmak için gereken işlev ise nasıl planlıyoruz :
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)
Python'da program yapmıyorum, ancak python.org'da S.rstrip'i ("\ r \ n") savunan bir python 2.2 veya üstü için SSS ile karşılaştım.
import re
r_unwanted = re.compile("[\n\t\r]")
r_unwanted.sub("", your_text)
Bir dosya nesnesinden kesilmemiş satırları alabilmenize paralel olarak, kesikli satırları yineleyici aracılığıyla elde edebilmeyi uygun buluyorum. Bunu aşağıdaki kodla yapabilirsiniz:
def chomped_lines(it):
return map(operator.methodcaller('rstrip', '\r\n'), it)
Örnek kullanım:
with open("file.txt") as infile:
for line in chomped_lines(infile):
process(line)
operator.methodcaller
ve map
( itertools.imap
Python seviyesi jeneratör kodunu kaçınarak (ve böylece olsa kuşkusuz I / O havai küçük kazançlar maskelemek muhtemeldir, biraz daha hızlı çalıştıran), C katmanına bu işi itebilir Py2 üzerine): for line in map(operator.methodcaller('rstrip', '\r\n'), infile):
. Yine de çarpanlarına ayrılabilir def chomped_lines(it): return map(operator.methodcaller('rstrip', '\r\n'), it)
.
özel durum için geçici çözüm:
eğer yeni satır karakteri son karakter ise (çoğu dosya girişinde olduğu gibi), o zaman koleksiyondaki herhangi bir eleman için aşağıdaki gibi indeksleyebilirsiniz:
foobar= foobar[:-1]
yeni satır karakterinizi dilimlemek için.
Perl'in chomp için mükemmel bir analog yok gibi görünüyor . Özellikle, rstrip gibi çok karakterli yeni satır sınırlayıcılarını işleyemez \r\n
. Ancak, splitlines burada belirtildiği gibi yapar . Farklı bir soru hakkındaki cevabımı takiben , bir dizeden tüm yeni satırları kaldırmak / değiştirmek için birleştirme ve ayırma çizgilerini birleştirebilirsinizs
:
''.join(s.splitlines())
Aşağıdaki kaldırır tam olarak bir arka satır (chomp, ben inanmak). Geçme True
olarak keepends
splitlines için argüman ayraçları korur. Ardından, yalnızca son "satır" daki sınırlayıcıları kaldırmak için tekrar bölme çizgileri çağrılır:
def chomp(s):
if len(s):
lines = s.splitlines(True)
last = lines.pop()
return ''.join(lines + last.splitlines())
else:
return ''
Daha önce başka bir cevabın yorumlarında gönderdiğim birinden düzenli ifade temelli cevabımı fırlatıyorum. Bence kullanmak re
bu soruna göre daha açık ve açık bir çözüm str.rstrip
.
>>> import re
Bir veya daha fazla sondaki yeni satır karakterini kaldırmak istiyorsanız :
>>> re.sub(r'[\n\r]+$', '', '\nx\r\n')
'\nx'
Newline karakterlerini her yerde kaldırmak istiyorsanız (yalnızca sondaki değil):
>>> re.sub(r'[\n\r]+', '', '\nx\r\n')
'x'
Yalnızca 1-2 sondaki yeni satır karakterleri kaldırmak istiyorsanız (yani \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'
Çoğu insanın burada gerçekten ne istediğini hissediyorum, sondaki yeni satır karakterinin tek bir örneğini kaldırmak ya \r\n
da \n
başka bir şey yok.
>>> 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'
( ?:
Yakalamayan bir grup oluşturmaktır.)
(Bu arada, bu iş parçacığı üzerinde tökezleyen başkaları için net olmayan bir şey '...'.rstrip('\n', '').rstrip('\r', '')
değildir. str.rstrip
Mümkün olan en fazla karakter dizer, bu nedenle bir dize foo\n\n\n
yanlış pozitif sonuç foo
verirken, korumak isteyebilirsiniz. tek bir sondaki sıyırdıktan sonra diğer yeni satırlar.)
r'\r?\n$'
. Muhtemelen daha verimlidir, çünkü regex motorları alternatifleri optimize etmek için daha zor zamanlara sahiptir. Ayrıca, bunu birçok kez yapacaksanız , ifadenin önüne bir kez daha önemli bir şekilde daha hızlı olacağını (özellikle başka re
kullanımlarla karışıyorsanız ) , derlenmiş normal ifade nesnesinin yöntemini re.compile
kullanın sub
; modül işlevleri Python düzeyindedir ve önce derlenmiş normal ifadeler için bir önbellek kontrol edin (eksikse oluşturma / önbellekleme), ardından eşleşen yöntemi çağırın; bu aramayı atlamak yardımcı olur.
\n
Doğrudan eşleştirmeye çalıştığınız için , \Z
üzerinde kullanmak isteyebilirsiniz $
(veya yalnızca eşleştirin \r?$
, çünkü $
örtük olarak bir dizenin sonundaki yeni satırdan hemen önce eşleşebilir).
>>> ' spacious '.rstrip()
' spacious'
>>> "AABAA".rstrip("A")
'AAB'
>>> "ABBA".rstrip("AB") # both AB and BA are stripped
''
>>> "ABCABBA".rstrip("AB")
'ABC'
"\r\n"
Örneğin: ' spacious \n\r\n\r \n\n'.rstrip()
üretir' spacious'
Sadece kullan :
line = line.rstrip("\n")
veya
line = line.strip("\n")
Bu karmaşık şeylerden hiçbirine ihtiyacınız yok
s = '''Hello World \t\n\r\tHi There'''
# import the module string
import string
# use the method translate to convert
s.translate({ord(c): None for c in string.whitespace}
>>'HelloWorldHiThere'
Normal ifade ile
s = ''' Hello World
\t\n\r\tHi '''
print(re.sub(r"\s+", "", s), sep='') # \s matches all white spaces
>HelloWorldHi
\ N, \ t, \ r yerine
s.replace('\n', '').replace('\t','').replace('\r','')
>' Hello World Hi '
Normal ifade ile
s = '''Hello World \t\n\r\tHi There'''
regex = re.compile(r'[\n\r\t]')
regex.sub("", s)
>'Hello World Hi There'
Join ile
s = '''Hello World \t\n\r\tHi There'''
' '.join(s.split())
>'Hello World Hi There'
Orada normalde karşılaşmak satır sonları üç tipi vardır: \n
, \r
ve \r\n
. Oldukça basit bir düzenli ifade re.sub
, yani r"\r?\n?$"
hepsini yakalayabilir.
(Ve hepsini yakalamalıyız , değil mi?)
import re
re.sub(r"\r?\n?$", "", the_text, 1)
Son argümanla, chomp'ı bir dereceye kadar taklit ederek, yerine geçen olay sayısını sınırlandırıyoruz. Misal:
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)
... nerede a == b == c
olduğunu True
.
rstrip("\r\n")
bir catch-all. Deneyin print(text_2.rstrip('\r\n'))
.
str.rstrip()
sorunu çözdüğü göz önüne alındığında . Hangi ihtiyaçlara sahip olduğunuza bağlıdır. Bu çözüm özellikle Üstelik geçen kaldırmak gerektiğinde durumlar için yapılır "\n"
, "\r"
ya da "\r\n"
ancak hepsi değil (birden varsa "\n"
dizede). farklı bir dize olan re.sub(r"\r?\n?$", "", text_1, 1)
döndürür "hellothere\n\n"
ve text_1.rstrip("\r\n")
döndürür "hellothere"
.
str.strip()
bir catch-all bazen çok sorun.
Hızla ilgili endişeleriniz varsa (dizelerinizde looong bir listeniz olduğunu varsayalım) ve newline char'ın doğasını biliyorsanız, dize dilimleme aslında rstrip'ten daha hızlıdır. Bunu göstermek için küçük bir test:
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()
Çıktı:
Method 1: 3.92700004578
Method 2: 6.73000001907
method1
sadece son karakteri, ne olursa olsun kapalı dorarken ilk çekler, eğer dize sonu istenmeyen karakterler içeriyor ve bazı bulundu yalnızca, onları doğruyor. Lütfen karakterleri kontrol edin ve hedefi test edin ! method2
.rstrip()
method1
Bu hem windows hem de linux için çalışacaktır (sadece yeniden çözüm arıyorsanız, re sub ile biraz pahalı)
import re
if re.search("(\\r|)\\n$", line):
line = re.sub("(\\r|)\\n$", "", line)
re.search
ihtiyacınız olanı kullanıyorsunuz re.sub
?
Hepsini yakala:
line = line.rstrip('\r|\n')
rstrip
düzenli ifade almaz. "hi|||\n\n".rstrip("\r|\n")
döner"hi"