chomp
ฟังก์ชันPython เทียบเท่ากับ Perl คืออะไรซึ่งจะลบอักขระตัวสุดท้ายของสตริงหากเป็นบรรทัดใหม่
open()
ไฟล์ที่มีพารามิเตอร์'newline = ... ' ที่เหมาะสมสำหรับแพลตฟอร์มของคุณ (สนับสนุนการขึ้นบรรทัดใหม่สากล) คุณอาจไม่จำเป็นต้องลบมันออกอย่างชัดเจน
chomp
ฟังก์ชันPython เทียบเท่ากับ Perl คืออะไรซึ่งจะลบอักขระตัวสุดท้ายของสตริงหากเป็นบรรทัดใหม่
open()
ไฟล์ที่มีพารามิเตอร์'newline = ... ' ที่เหมาะสมสำหรับแพลตฟอร์มของคุณ (สนับสนุนการขึ้นบรรทัดใหม่สากล) คุณอาจไม่จำเป็นต้องลบมันออกอย่างชัดเจน
คำตอบ:
ลองวิธีการrstrip()
(ดู doc Python 2และPython 3 )
>>> 'test string\n'.rstrip()
'test string'
ธrstrip()
วิธีแถบทุกชนิดของช่องว่างต่อท้ายโดยค่าเริ่มต้นไม่ได้เป็นเพียงหนึ่งบรรทัดใหม่เป็น Perl chomp
จะมี
>>> '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'
\n
สำหรับการขึ้นบรรทัดใหม่เหมือนกับ Unix (ก่อนที่จะมี OS X, MacOS ได้ใช้\r
เป็นตัวคั่นบรรทัด แต่ที่สิ้นสุดวันที่ 10 ปีที่ผ่านมา.)
.strip()
ไม่เปลี่ยนสตริง (อาจมีบางสิ่งที่เกี่ยวข้องกับสตริงที่ไม่เปลี่ยนรูป) ถ้าไม่อยู่ในบรรทัดคำสั่งคุณจะต้อง"string = string.strip()"
และฉันจะบอกว่าวิธีการ "pythonic" เพื่อรับสายโดยไม่ต้องต่อท้ายอักขระบรรทัดใหม่คือ splitline ()
>>> text = "line 1\nline 2\r\nline 3\nline 4"
>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']
วิธีที่เป็นที่ยอมรับในการตัดอักขระ end-of-line (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'
การใช้ '\ r \ n' เป็นพารามิเตอร์ในการ rstrip หมายความว่ามันจะตัดการผสมต่อท้ายใด ๆ ของ '\ r' หรือ '\ n' นั่นเป็นเหตุผลที่ทำงานได้ในทั้งสามกรณีข้างต้น
ความแตกต่างนี้มีความสำคัญในกรณีที่หายาก ตัวอย่างเช่นฉันเคยต้องประมวลผลไฟล์ข้อความที่มีข้อความ HL7 มาตรฐาน HL7 ต้องใช้ '\ r' ต่อท้ายเป็นอักขระ EOL เครื่อง Windows ที่ฉันใช้ข้อความนี้ได้ผนวกอักขระ EOL '\ r \ n' ของตัวเอง ดังนั้นจุดสิ้นสุดของแต่ละบรรทัดจึงดูเหมือน '\ r \ r \ n' การใช้ rstrip ('\ r \ n') น่าจะเอาทั้งหมด '\ r \ r \ n' ซึ่งไม่ใช่สิ่งที่ฉันต้องการ ในกรณีนั้นฉันเพียงแค่ตัดสองอักขระสุดท้ายแทน
โปรดทราบว่าไม่เหมือนกับchomp
ฟังก์ชันของ Perl สิ่งนี้จะตัดอักขระที่ระบุทั้งหมดที่ส่วนท้ายของสตริงไม่ใช่เพียงตัวอักษรเดียว
>>> "Hello\n\n\n".rstrip("\n")
"Hello"
os.linesep
มีซึ่งมีลำดับ EOL สำหรับระบบปฏิบัติการปัจจุบัน
\n
และ\r
โปรดทราบว่า rstrip ไม่เหมือนกับ chomp ของ Perl () เพราะมันไม่ได้ปรับเปลี่ยนสตริง นั่นคือใน Perl:
$x="a\n";
chomp $x
ส่งผลให้ความเป็นอยู่$x
"a"
แต่ใน Python:
x="a\n"
x.rstrip()
จะหมายความว่าค่าของx
เป็นยัง "a\n"
แม้x=x.rstrip()
จะไม่ได้ผลเหมือนกันเสมอไปเพราะมันตัดช่องว่างทั้งหมดออกจากส่วนท้ายของสตริงไม่ใช่แค่ขึ้นบรรทัดใหม่มากที่สุด
ฉันอาจใช้สิ่งนี้:
import os
s = s.rstrip(os.linesep)
ฉันคิดว่าปัญหาที่เกิดขึ้นrstrip("\n")
คือคุณอาจต้องการตรวจสอบให้แน่ใจว่าตัวแยกบรรทัดเป็นแบบพกพา (ระบบโบราณบางระบบมีข่าวลือให้ใช้"\r\n"
) gotcha อื่น ๆ ที่rstrip
จะตัดช่องว่างซ้ำออกมา หวังว่าos.linesep
จะมีตัวอักษรที่เหมาะสม ข้างต้นใช้งานได้สำหรับฉัน
rstrip('\r\n')
และrstrip()
จะดึงตัวละครที่อยู่ในการโต้แย้ง
line = line.rstrip('\n')
คุณอาจจะใช้ สิ่งนี้จะตัดการขึ้นบรรทัดใหม่ทั้งหมดจากจุดสิ้นสุดของสตริงไม่ใช่แค่หนึ่งบรรทัด
s = s.rstrip()
s
จะลบบรรทัดใหม่ทั้งหมดในตอนท้ายของสตริง การกำหนดเป็นสิ่งจำเป็นเนื่องจากrstrip
ส่งคืนสตริงใหม่แทนการแก้ไขสตริงเดิม
สิ่งนี้จะทำซ้ำ chomp ของ perl (ลบพฤติกรรมในอาร์เรย์) ของตัวคั่นบรรทัด "\ 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
(หมายเหตุ: มันไม่ได้แก้ไขสตริง 'ในสถานที่' มันไม่ได้ตัดช่องว่างต่อท้ายพิเศษใช้เวลา \ r \ n ในบัญชี)
"line 1\nline 2\r\n...".replace('\n', '').replace('\r', '')
>>> 'line 1line 2...'
หรือคุณสามารถรับ geekier ด้วย regexps :)
มีความสุข!
.replace('\n|\r', '')
?
import re
re.sub('\n|\r', '', '\nx\n\r\n')
'x'
คุณสามารถใช้แถบ:
line = line.strip()
การสาธิต:
>>> "\n\n hello world \n\n".strip()
'hello world'
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'
ระวังด้วย"foo".rstrip(os.linesep)
: นั่นจะทำให้ตัวละครขึ้นบรรทัดใหม่สำหรับแพลตฟอร์มที่ใช้งาน Python ของคุณเท่านั้น ลองจินตนาการว่าคุณกำลังทำให้ไฟล์ใน Windows ภายใต้ Linux เป็นตัวอย่าง:
$ 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")
แทนอย่างที่ Mike พูดด้านบน
chomp
แต่การขึ้นบรรทัดใหม่ทั้งหมดซึ่งแตกต่างจาก
เช่นในเอกสารของงูใหญ่line.strip()
เพียงแค่ใช้
chomp
ฟังก์ชั่นของ Perl ลบลำดับบรรทัดเดียวออกจากจุดสิ้นสุดของสตริงเฉพาะถ้ามันมีจริง
นี่คือวิธีที่ฉันวางแผนที่จะทำเช่นนั้นใน Python ถ้าprocess
เป็นแนวคิดฟังก์ชั่นที่ฉันต้องการเพื่อทำสิ่งที่มีประโยชน์สำหรับแต่ละบรรทัดจากไฟล์นี้:
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)
import re
r_unwanted = re.compile("[\n\t\r]")
r_unwanted.sub("", your_text)
ฉันคิดว่ามันสะดวกที่จะสามารถรับสาย chomped ผ่านในตัววนซ้ำขนานกับวิธีที่คุณสามารถรับสายที่ไม่ได้ chomped จากวัตถุไฟล์ คุณสามารถทำได้ด้วยรหัสต่อไปนี้:
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)
operator.methodcaller
และmap
( itertools.imap
ใน Py2) คุณสามารถผลักดันงานนี้ไปยังชั้น C หลีกเลี่ยงงูหลามรหัสเครื่องกำเนิดไฟฟ้าระดับ (และจึงวิ่งบิตเร็วขึ้น แต่ยอมรับ I / O for line in map(operator.methodcaller('rstrip', '\r\n'), infile):
ค่าใช้จ่ายมีแนวโน้มที่จะสวมหน้ากากกำไรเล็ก): def chomped_lines(it): return map(operator.methodcaller('rstrip', '\r\n'), it)
มันอาจจะยังคงได้รับปัจจัยจากการเป็น
วิธีแก้ปัญหาสำหรับกรณีพิเศษ:
หากอักขระขึ้นบรรทัดใหม่เป็นอักขระตัวสุดท้าย (ตามที่เป็นกรณีที่มีอินพุตไฟล์ส่วนใหญ่) ดังนั้นสำหรับองค์ประกอบใด ๆ ในคอลเลกชันคุณสามารถสร้างดัชนีได้ดังนี้:
foobar= foobar[:-1]
เพื่อแบ่งอักขระขึ้นบรรทัดใหม่ของคุณ
หากคำถามของคุณคือการล้างการขึ้นบรรทัดใหม่ทั้งหมดในวัตถุหลายบรรทัด str (oldstr) คุณสามารถแบ่งออกเป็นรายการตามตัวคั่น '\ n' จากนั้นเข้าร่วมรายการนี้เป็น str ใหม่ (newstr)
newstr = "".join(oldstr.split('\n'))
ดูเหมือนว่ามีไม่ได้เป็นอะนาล็อกที่สมบูรณ์แบบสำหรับของ Perl chomp โดยเฉพาะอย่างยิ่งrstripไม่สามารถจัดการตัวคั่นบรรทัดใหม่หลายตัวละคร\r\n
ได้ อย่างไรก็ตามsplitlinesไม่เป็นแหลมออกจากที่นี่ ทำตามคำตอบของฉันในคำถามที่แตกต่างกันคุณสามารถรวมเข้าร่วมและแยกเพื่อลบ / แทนที่บรรทัดใหม่ทั้งหมดจากสตริงs
:
''.join(s.splitlines())
ต่อไปนี้จะลบnewline ต่อท้ายหนึ่งบรรทัด (อย่างที่ฉันเชื่อว่า chomp) ผ่านTrue
เป็นkeepends
อาร์กิวเมนต์เพื่อแยกบรรทัดเก็บตัวคั่น จากนั้นเส้นแบ่งจะถูกเรียกอีกครั้งเพื่อลบตัวคั่นบน "บรรทัด" สุดท้าย:
def chomp(s):
if len(s):
lines = s.splitlines(True)
last = lines.pop()
return ''.join(lines + last.splitlines())
else:
return ''
ฉันตอบคำถามตามนิพจน์ปกติของฉันจากโพสต์ก่อนหน้านี้ในข้อคิดเห็นของคำตอบอื่น ฉันคิดว่าการใช้re
เป็นวิธีแก้ปัญหาที่ชัดเจนกว่าstr.rstrip
นี้
>>> import re
หากคุณต้องการที่จะลบหนึ่งหรือมากกว่าต่อท้ายตัวอักษรขึ้นบรรทัดใหม่:
>>> 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
มากกว่านั้น
>>> 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'
( ?:
คือการสร้างกลุ่มที่ไม่จับภาพ)
(โดยวิธีการนี้ไม่ใช่สิ่ง'...'.rstrip('\n', '').rstrip('\r', '')
ที่อาจไม่ชัดเจนสำหรับผู้อื่นที่สะดุดเมื่อเธรดนี้ str.rstrip
ดึงอักขระที่ต่อท้ายมากที่สุดเท่าที่เป็นไปได้ดังนั้นสตริงที่เหมือนfoo\n\n\n
จะส่งผลในเชิงบวกผิด ๆ ในfoo
ขณะที่คุณอาจต้องการรักษา ขึ้นบรรทัดใหม่อื่น ๆ หลังจากทำการลากส่วนท้ายหนึ่งอัน)
r'\r?\n$'
regex มีประสิทธิภาพมากขึ้นเนื่องจากเอ็นจิ้นของ regex มีช่วงเวลาที่ยากขึ้นในการปรับการสับเปลี่ยน นอกจากนี้โปรดทราบว่าหากคุณจะทำเช่นนี้หลาย ๆ ครั้งมันจะเร็วขึ้นอย่างมาก (โดยเฉพาะถ้าคุณผสมกับการre
ใช้งานอื่น ๆ) ในre.compile
การแสดงออกครั้งเดียวล่วงหน้าจากนั้นใช้sub
วิธีการของวัตถุ regex ที่รวบรวม ฟังก์ชั่นโมดูลเป็นระดับ Python และตรวจสอบแคชสำหรับการรวบรวม regexes ก่อน (การสร้าง / แคชหากไม่มี) จากนั้นเรียกวิธีการจับคู่; การข้ามการค้นหานั้นช่วยได้
\n
โดยตรงคุณอาจต้องการใช้\Z
เกิน$
(หรือเพียงแค่จับคู่\r?$
เนื่องจาก$
โดยปริยายสามารถจับคู่ก่อนขึ้นบรรทัดใหม่ในตอนท้ายของสตริง)
>>> ' spacious '.rstrip()
' spacious'
>>> "AABAA".rstrip("A")
'AAB'
>>> "ABBA".rstrip("AB") # both AB and BA are stripped
''
>>> "ABCABBA".rstrip("AB")
'ABC'
"\r\n"
ตัวอย่างเช่น: ' spacious \n\r\n\r \n\n'.rstrip()
ผลิต' spacious'
เพียงใช้:
line = line.rstrip("\n")
หรือ
line = line.strip("\n")
คุณไม่ต้องการสิ่งที่ซับซ้อนนี้
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'
ด้วย regex
s = ''' Hello World
\t\n\r\tHi '''
print(re.sub(r"\s+", "", s), sep='') # \s matches all white spaces
>HelloWorldHi
แทนที่ \ n, \ t, \ r
s.replace('\n', '').replace('\t','').replace('\r','')
>' Hello World Hi '
ด้วย regex
s = '''Hello World \t\n\r\tHi There'''
regex = re.compile(r'[\n\r\t]')
regex.sub("", s)
>'Hello World Hi There'
ด้วยการเข้าร่วม
s = '''Hello World \t\n\r\tHi There'''
' '.join(s.split())
>'Hello World Hi There'
มีสามประเภทของปลายสายที่เรามักพบคือ\n
, และ\r
\r\n
การแสดงออกปกติค่อนข้างง่ายre.sub
คือr"\r?\n?$"
สามารถจับพวกเขาทั้งหมด
(และเราต้องจับพวกเขาทั้งหมดใช่มั้ย)
import re
re.sub(r"\r?\n?$", "", the_text, 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("\r\n")
เป็นสิ่งที่จับได้ทั้งหมด ลองprint(text_2.rstrip('\r\n'))
ดู
str.rstrip()
แก้ปัญหา ขึ้นอยู่กับความต้องการของคุณ การแก้ปัญหานี้จะทำเฉพาะสำหรับกรณีเมื่อคุณต้องการที่จะลบเพียงสุดท้าย"\n"
, "\r"
หรือ"\r\n"
แต่ไม่ทั้งหมดของพวกเขา (ถ้ามีหลาย"\n"
ในสตริง) re.sub(r"\r?\n?$", "", text_1, 1)
ผลตอบแทน"hellothere\n\n"
และtext_1.rstrip("\r\n")
ผลตอบแทน"hellothere"
ซึ่งเป็นสตริงที่แตกต่างกัน
str.strip()
คือสิ่งที่จับได้บางครั้งก็เป็นปัญหาอย่างมาก
หากคุณกังวลเกี่ยวกับความเร็ว (สมมติว่าคุณมีรายการสตริงที่ยาวเหยียด) และคุณรู้ว่าลักษณะของอักขระขึ้นบรรทัดใหม่การแบ่งสตริงเป็นจริงเร็วกว่า 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
method1
คุณเพียงแค่ตัดอักขระตัวสุดท้ายไม่ว่าจะเกิดอะไรขึ้นในmethod2
การ.rstrip()
ตรวจสอบครั้งแรกหากการสิ้นสุดของสตริงมีอักขระที่ไม่พึงประสงค์และตัดออกหากพบบางอย่างเท่านั้น โปรดใช้การตรวจสอบตัวละครmethod1
และทดสอบความเจ็บปวด!
สิ่งนี้จะทำงานได้ทั้งกับ windows และ linux (ราคาแพงไปอีกเล็กน้อยหากคุณกำลังมองหาวิธีแก้ปัญหาเท่านั้น)
import re
if re.search("(\\r|)\\n$", line):
line = re.sub("(\\r|)\\n$", "", line)
re.search
ที่คุณเพียงแค่ต้องre.sub
?
แยกบรรทัดแรกแล้วเข้าร่วมโดยตัวแยกที่คุณต้องการ:
x = ' '.join(x.splitlines())
ควรทำงานเหมือนมีเสน่ห์
จับทั้งหมด:
line = line.rstrip('\r|\n')
rstrip
ไม่แสดงออกอย่างสม่ำเสมอ "hi|||\n\n".rstrip("\r|\n")
ผลตอบแทน"hi"