วิธีลบ JavaScript และแท็กอื่น ๆ โดยใช้ Python ... โดยไม่ต้องนำเข้าโมดูล
สำหรับส่วนแรกของโครงการโรงเรียนฉันพยายามที่จะคิดออกว่าจะเอา JavaScript <script {...} >และ</script {...} >แท็กเช่นเดียวกับอะไรระหว่างและ<>
อย่างไรก็ตามเราไม่สามารถนำเข้าโมดูลใด ๆ (แม้จะสร้างใน Python ก็ตาม) เนื่องจากเห็นได้ชัดว่าเครื่องหมายอาจไม่สามารถเข้าถึงได้เป็นต้น
ฉันลองสิ่งนี้:
text = "<script beep beep> hello </script boop doop woop> hello <hi> hey <bye>"
while text.find("<script") >= 0:
script_start = text.find("<script")
script_end = text.find(">", text.find("</script")) + 1
text = text[:script_start] + text[script_end:]
while text.find("<") >= 0:
script2_start = text.find("<")
script2_end = text.find(">") + 1
text = text[:script2_start] + text[script2_end:]
และนั่นใช้ได้กับไฟล์ขนาดเล็ก แต่โปรเจ็กต์เกี่ยวข้องกับไฟล์ข้อความขนาดใหญ่ (การทดสอบแบบง่ายที่เราได้รับคือ 10.4MB) ดังนั้นมันจึงไม่เสร็จสิ้นและมันก็ค้างอยู่
ใครมีความคิดที่จะทำให้มีประสิทธิภาพมากขึ้น?
คำตอบ
คุณไม่จำเป็นต้องลบอะไร ในความเป็นจริง: คุณไม่ต้องการแก้ไขสตริง
สตริงเป็นสิ่งที่ไม่เปลี่ยนแปลง: ทุกครั้งที่คุณ "แก้ไข" สตริงคุณจะต้องสร้างสตริงใหม่และทิ้งอันเก่า นั่นเป็นการสิ้นเปลืองหน่วยประมวลผลและหน่วยความจำ
คุณกำลังใช้งานไฟล์ - ดังนั้นให้ประมวลผลตามตัวอักษร:
- จำไว้ว่าคุณอยู่ข้างใน
<...>หรือไม่ - ถ้าเป็นเช่นนั้นตัวละครที่สำคัญเท่านั้นที่
>จะได้ออกไปข้างนอกอีกครั้ง - หากภายนอกและตัวละคร
<คุณเข้าไปข้างในและไม่สนใจตัวละครนั้น - ถ้าภายนอกและ
<คุณไม่ได้เขียนอักขระลงในเอาต์พุต (-file)
# create file
with open("somefile.txt","w") as f:
# up the multiplicator to 10000000 to create something in the megabyte range
f.write("<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata\n"*10)
# open file to read from and file to write to
with open("somefile.txt") as f, open("otherfile.txt","w") as out:
# starting outside
inside = False
# we iterate the file line by line
for line in f:
# and each line characterwise
for c in line:
if not inside and c == "<":
inside = True
elif inside and c != ">":
continue
elif inside and c == ">":
inside = False
elif not inside:
# only case to write to out
out.write(c)
print(open("somefile.txt").read() + "\n")
print(open("otherfile.txt").read())
เอาท์พุต:
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
hello hello hey tata
หากคุณไม่ได้รับอนุญาตให้ใช้งานไฟล์โดยตรงให้อ่านไฟล์ในรายการที่ใช้หน่วยความจำ 11 + Mbyte:
data = list("<script beep beep> hello </script boop doop woop> hello <hi> hey <bye> tata\n" * 10)
result = []
inside = False
for c in data:
if inside:
if c == ">":
inside = False
# else ignore c - because we are inside
elif c == "<":
inside = True
else:
result.append(c)
print(''.join(result))
สิ่งนี้ยังดีกว่าจากนั้นค้นหาการเกิดครั้งแรกของ "<" ซ้ำ ๆ ในรายการ แต่อาจต้องใช้หน่วยความจำมากถึงสองเท่าของแหล่งที่มาของคุณ (หากไม่มี <.. > คุณจะเพิ่มรายการเป็นสองเท่า)
การใช้งานไฟล์นั้นมีหน่วยความจำที่มีประสิทธิภาพมากกว่าจากนั้นทำการปรับเปลี่ยนรายการแบบแทนที่ (ซึ่งจะเป็นวิธีที่สามในการดำเนินการนี้)
มีบางสิ่งที่น่าสนใจที่คุณต้องใช้ในการหลีกเลี่ยง fe
<script type="text/javascript">
var i = 10;
if (i < 5) {
// some code
}
</script>
จะทิ้ง "รหัส" ไว้ข้างใน
สิ่งนี้อาจทำให้กรณีมุมง่ายขึ้น:
# open file to read from and file to write to
with open("somefile.txt") as f, open("otherfile.txt","w") as out:
# starting outside
inside = False
insideJS = False
jsStart = 0
# we iterate the file line by line
for line in f:
# string manipulation :/ - will remove <script ...> .. </script ..>
# even over multiple lines - probably missed some cornercases.
while True:
if insideJS and not "</script" in line:
line = ""
break
if "<script" in line:
insideJS = True
jsStart = line.index("<script")
jsEnd = len(line)
elif insideJS:
jsStart = 0
if not insideJS:
break
if "</script" in line:
jsEnd = line.index(">", line.index("</script", jsStart))+1
line = line[:jsStart] + line[jsEnd:]
insideJS = False
else:
line = line[:jsStart]
# and each line characterwise
for c in line:
# ... same as above ...
แม้ว่าจะมี 2 while ลูป แต่ก็ยังคงเป็นความซับซ้อนเชิงเส้น
string = "<script beep beep> hello </script boop doop woop> hello <hi> hey <bye>"
new_string = ''
i = 0
while i < len(string):
if string[i] == "<":
while i < len(string):
i += 1
if string[i] == '>':
break
else:
new_string += string[i]
i += 1
print(new_string)
ผลลัพธ์:
hello hello hey
นี่คือแนวทางหนึ่งของFSA :
output = ''
NORMAL, INSIDE_TAG = range(2) # availale states
state = NORMAL # start with normal state
s = '<script beep beep> hello </script boop doop woop> hello <hi id="someid" class="some class"><a> hey </a><bye>'
for char in s:
if char == '<': # if we encounter '<' we enter the INSIDE_TAG state
state = INSIDE_TAG
continue
elif char == '>': # we can safely exit the INSIDE_TAG state
state = NORMAL
continue
if state == NORMAL:
output += char # add the char to the output only if we are in normal state
print(output)
หากต้องการแยกวิเคราะห์ความหมายของแท็กตรวจสอบให้แน่ใจว่าได้ใช้ stack (สามารถใช้งานได้กับlist)
มันจะเพิ่มความซับซ้อน แต่คุณจะได้รับการตรวจสอบที่มีประสิทธิภาพด้วย FSM
ดูตัวอย่างต่อไปนี้:
output = ''
(
NORMAL,
TAG_ATTRIBUTE,
INSIDE_JAVASCRIPT,
EXITING_TAG,
BEFORE_TAG_OPENING_OR_ENDING,
TAG_NAME,
ABOUT_TO_EXIT_JS
) = range(7) # availale states
state = NORMAL # start with normal state
tag_name = ''
s = """
<script type="text/javascript">
var i = 10;
if (i < 5) {
// some code
}
</script>
<sometag>
test string
<a href="http://google.com"> another string</a>
</sometag>
"""
for char in s:
# print(char, '-', state, ':', tag_name)
if state == NORMAL:
if char == '<':
state = BEFORE_TAG_OPENING_OR_ENDING
else:
output += char
elif state == BEFORE_TAG_OPENING_OR_ENDING:
if char == '/':
state = EXITING_TAG
else:
tag_name += char
state = TAG_NAME
elif state == TAG_ATTRIBUTE:
if char == '>':
if tag_name == 'script':
state = INSIDE_JAVASCRIPT
else:
state = NORMAL
elif state == TAG_NAME:
if char == ' ':
state = TAG_ATTRIBUTE
elif char == '>':
if tag_name == 'script':
state = INSIDE_JAVASCRIPT
else:
state = NORMAL
else:
tag_name += char
elif state == INSIDE_JAVASCRIPT:
if char == '<':
state = ABOUT_TO_EXIT_JS
else:
pass
# output += char
elif state == ABOUT_TO_EXIT_JS:
if char == '/':
state = EXITING_TAG
tag_name = ''
else:
# output += '<'
state = INSIDE_JAVASCRIPT
elif state == EXITING_TAG:
if char == '>':
state = NORMAL
print(output)
เอาท์พุท:
test string
another string