用指定的替换字符串替换文件中的单词并处理缩进级别
Replace words in a file with specified replacement string and handle indent level
所以我有一个练习。我必须编写一个 python 脚本来查找实际文件夹中扩展名为“.prog”的所有文件。 (程序的这一部分已经可以运行)。这个 prog 文件看起来像这样:
import sys
n = int(sys.argv[1]) ;print "Start of the program!"
LOOP i in range(1,n) [[print "The number:";print i]]
DECISION n < 5 [[print n ;print "smaller then 5"]]
输出应该是这样的:
import sys
n = int(sys.argv[1])
print "Start of the program!"
for i in range(1,n) :
print "The number:"
print i
if n < 5 :
print n
print "smaller then 5"
所以我必须将 LOOP 替换为 for,将 DECISION 替换为 if。它可以是“;”之前的 space,但不能在它之后。 '[[**]]' 始终包含 python 语句。
在 for 循环和 if 语句之后,命令总是必须在四个 space 之后开始。
这是我的代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def find():
import glob, os
os.chdir(os.getcwd())
for file in glob.glob("*.prog"):
ProgToPy(file)
def ProgToPy(f):
outname = f.replace("prog","py")
replacements = {'LOOP':'for', 'DECISION':'if', ' ;':'\n', ';':'\n ', ' [[':' :\n ', ']]':''}
with open(f) as infile, open(outname, 'w') as outfile:
for line in infile:
for src, target in replacements.iteritems():
line = line.replace(src, target)
outfile.write(line)
find()
问题在于我的输出如下所示:
import sys
n = int(sys.argv[1])
print "Start of the program!"
for i in range(1,n) :
print "The number:"
print i
if n < 5 :
print n
print "smaller then 5"
如果我在替换中加入这样的内容 ' ;':'\n '
。第一个打印将在四个 space 之后立即开始。然后创建的 .py
文件无法正常工作。
您可以使用正则表达式来解决您的问题。
import re
import glob, os
pattern = r'(.*)\[\[(.*)\]\]'
regex = re.compile(pattern)
def ProgToPy(f):
outname = f.replace("prog","py")
replacements = {'LOOP':'for', 'DECISION':'if', ';': '\n\t'}
with open(f) as infile, open(outname, 'w') as outfile:
for line in infile:
m = regex.match(line)
if m:
line = ''
for matched_part in m.groups():
line += matched_part + '\n\t'
for src, target in replacements.iteritems():
line = line.replace(src, target)
outfile.write(line)
os.chdir(os.getcwd())
for file in glob.glob("*.prog"):
ProgToPy(file)
由于分号根据其位置的不同而有所不同,因此您基本上应该为每个状态编写单独的函数。 [[...]]
表示 Python 中的块作用域,所以我们称这些状态为 normal state
和 block state
。
为了控制状态,我们将使用布尔变量 in_block
并使用正则表达式来确定其值。
这里,我把所有的替换任务都放在了一个replaceTokens
函数中。
def replaceTokens(statement, in_block=False):
if in_block:
statement = statement.replace(SEMI, NEWLINE+TABSPACE)
statement = statement.replace(OPEN_BRACKETS, COLON+NEWLINE+TABSPACE)
else:
statement = statement.replace(SEMI, NEWLINE)
statement = statement.replace(OPEN_BRACKETS, COLON+NEWLINE)
statement = statement.replace(CLOSE_BRACKETS, NEWLINE)
statement = statement.replace(LOOP, FOR)
statement = statement.replace(DECISION, IF)
return statement
上面的代码看起来很乏味,但如果你愿意,你可以轻松地为此编写一个 for
循环。这里重要的一点是我使用的是布尔变量 in_block
。这使您可以根据双括号的存在来决定是否在换行符后跟一个制表符。
要在块范围内查找语句,我使用正则表达式:
def progToPy(f):
outname = f.replace("prog","py")
rf = open(f, "r")
text = rf.read()
rf.close()
block_regex = re.compile(r'\[\[.*\]\]')
mo = block_regex.findall(text)
for match in mo:
statement = blockScope(match)
text = text.replace(match, statement)
text = replaceTokens(text)
print(text)
blockScope
函数仅用in_block=True
替换块范围内的语句,然后先替换那些部分。然后,当我们对整个文档调用 replaceTokens
时,块范围内的那些已经被替换,因此不会受到第二次调用的影响。
def blockScope(block):
statement = replaceTokens(block, in_block=True)
return statement
所以我有一个练习。我必须编写一个 python 脚本来查找实际文件夹中扩展名为“.prog”的所有文件。 (程序的这一部分已经可以运行)。这个 prog 文件看起来像这样:
import sys
n = int(sys.argv[1]) ;print "Start of the program!"
LOOP i in range(1,n) [[print "The number:";print i]]
DECISION n < 5 [[print n ;print "smaller then 5"]]
输出应该是这样的:
import sys
n = int(sys.argv[1])
print "Start of the program!"
for i in range(1,n) :
print "The number:"
print i
if n < 5 :
print n
print "smaller then 5"
所以我必须将 LOOP 替换为 for,将 DECISION 替换为 if。它可以是“;”之前的 space,但不能在它之后。 '[[**]]' 始终包含 python 语句。 在 for 循环和 if 语句之后,命令总是必须在四个 space 之后开始。 这是我的代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def find():
import glob, os
os.chdir(os.getcwd())
for file in glob.glob("*.prog"):
ProgToPy(file)
def ProgToPy(f):
outname = f.replace("prog","py")
replacements = {'LOOP':'for', 'DECISION':'if', ' ;':'\n', ';':'\n ', ' [[':' :\n ', ']]':''}
with open(f) as infile, open(outname, 'w') as outfile:
for line in infile:
for src, target in replacements.iteritems():
line = line.replace(src, target)
outfile.write(line)
find()
问题在于我的输出如下所示:
import sys
n = int(sys.argv[1])
print "Start of the program!"
for i in range(1,n) :
print "The number:"
print i
if n < 5 :
print n
print "smaller then 5"
如果我在替换中加入这样的内容 ' ;':'\n '
。第一个打印将在四个 space 之后立即开始。然后创建的 .py
文件无法正常工作。
您可以使用正则表达式来解决您的问题。
import re
import glob, os
pattern = r'(.*)\[\[(.*)\]\]'
regex = re.compile(pattern)
def ProgToPy(f):
outname = f.replace("prog","py")
replacements = {'LOOP':'for', 'DECISION':'if', ';': '\n\t'}
with open(f) as infile, open(outname, 'w') as outfile:
for line in infile:
m = regex.match(line)
if m:
line = ''
for matched_part in m.groups():
line += matched_part + '\n\t'
for src, target in replacements.iteritems():
line = line.replace(src, target)
outfile.write(line)
os.chdir(os.getcwd())
for file in glob.glob("*.prog"):
ProgToPy(file)
由于分号根据其位置的不同而有所不同,因此您基本上应该为每个状态编写单独的函数。 [[...]]
表示 Python 中的块作用域,所以我们称这些状态为 normal state
和 block state
。
为了控制状态,我们将使用布尔变量 in_block
并使用正则表达式来确定其值。
这里,我把所有的替换任务都放在了一个replaceTokens
函数中。
def replaceTokens(statement, in_block=False):
if in_block:
statement = statement.replace(SEMI, NEWLINE+TABSPACE)
statement = statement.replace(OPEN_BRACKETS, COLON+NEWLINE+TABSPACE)
else:
statement = statement.replace(SEMI, NEWLINE)
statement = statement.replace(OPEN_BRACKETS, COLON+NEWLINE)
statement = statement.replace(CLOSE_BRACKETS, NEWLINE)
statement = statement.replace(LOOP, FOR)
statement = statement.replace(DECISION, IF)
return statement
上面的代码看起来很乏味,但如果你愿意,你可以轻松地为此编写一个 for
循环。这里重要的一点是我使用的是布尔变量 in_block
。这使您可以根据双括号的存在来决定是否在换行符后跟一个制表符。
要在块范围内查找语句,我使用正则表达式:
def progToPy(f):
outname = f.replace("prog","py")
rf = open(f, "r")
text = rf.read()
rf.close()
block_regex = re.compile(r'\[\[.*\]\]')
mo = block_regex.findall(text)
for match in mo:
statement = blockScope(match)
text = text.replace(match, statement)
text = replaceTokens(text)
print(text)
blockScope
函数仅用in_block=True
替换块范围内的语句,然后先替换那些部分。然后,当我们对整个文档调用 replaceTokens
时,块范围内的那些已经被替换,因此不会受到第二次调用的影响。
def blockScope(block):
statement = replaceTokens(block, in_block=True)
return statement