我正在使用python中的一个转换器,我的代码的一个功能是找到某些符号并在它们周围放置空格,以便以后更容易解析。
这是最初放置在字符周围空格的代码
def InsertSpaces(string):
to_return = list(string)
for i, char in enumerate(to_return):
if char == '?' or char == '#' or char == '@':
to_return[i] = (to_return[i] + ' ')[::-1]
to_return[i] += ' '
print(''.join(to_return))
虽然这有效,但它造成了一个烦人的问题
它在换行符之后创建了空格,这可能会导致以后出现问题并且只是丑陋。
所以这个:
'@0x0D?0A\n@0x1f?@0x2f?48#65#6C#6C#6F#2C#20#57#6F#72#6C#64#21'
成为这个:
' @ 0x0D ? 0A
@ 0x1f ? @ 0x2f ? 48 # 65 # 6C # 6C # 6F # 2C # 20 # 57 # 6F # 72 # 6C # 64 # 21'
(请记住,这会将字符串拆分为列表)
所以我写了这个来检测列表中的换行符,之后我会删除空格。
for char in to_return:
char_next = to_return[to_return.index(char) + 1]
if (char + char_next) == '':
print('found a newline')
问题是它没有检测到任何换行符。
打印你可以看到换行符的字符对,但是代码找不到它,因为它变成了一个新行,我认为它不能用简单的字符串读取。
@ 0
0x
x0
0x
D ?
? 0
0x
A
@
@ 0
0x
x0
1f
f ?
? 0
@ 0
0x
x0
2f
f ?
? 0
48
8 #
# 6
65
5 #
# 6
65
C #
# 6
65
C #
# 6
65
F #
# 6
2f
C #
# 6
2f
0x
# 6
5 #
7 #
# 6
65
F #
# 6
7 #
2f
# 6
65
C #
# 6
65
48
# 6
2f
1f
有没有办法在迭代字符串列表时检测换行符?
答案 0 :(得分:2)
首先,这是一段奇怪的代码:
to_return[i] = (to_return[i] + ' ')[::-1]
to_return[i]
是一个字符长,所以这一行等同于:
to_return[i] = ' ' + to_return[i]
其次,如果您只是尝试使用空格填充所有'?','#'和'@',为什么不尝试简单替换:
def InsertSpaces(string):
return string.replace("?"," ? ").replace("#", " # ").replace("@", " @ ")
如果使用re
(正则表达式)模块,则更短:
def InsertSpace(string):
return re.sub("(#|\?|@)",r" \1 ", string)
答案 1 :(得分:1)
迭代当前的char和下一个char并使用'\n'
:
for char, char_next in zip(to_return, to_return[1:]):
if char + char_next == '\n ':
print('found a newline')
答案 2 :(得分:1)
这是一种修改函数以解决问题而无需正则表达式的方法。
在每次迭代中检查前一个或下一个字符是否为新行。在这些情况下,请勿添加空格:
def InsertSpaces(s):
to_return = []
for i, char in enumerate(s):
if char in {'?', '#', '@'}:
val = ' ' if ((i-1) > 0) and s[i-1] != '\n' else ''
val += char
val += ' ' if ((i+1) < len(s)) and s[i+1] != '\n' else ''
else:
val = char
to_return.append(val)
return ''.join(to_return)
s = '@0x0D?0A\n@0x1f?@0x2f?48#65#6C#6C#6F#2C#20#57#6F#72#6C#'
print(repr(InsertSpaces(s)))
#'@ 0x0D ? 0A\n@ 0x1f ? @ 0x2f ? 48 # 65 # 6C # 6C # 6F # 2C # 20 # 57 # 6F # 72 # 6C #'
关键是这一部分:
val = ' ' if ((i-1) > 0) and s[i-1] != '\n' else '' #1
val += char #2
val += ' ' if ((i+1) < len(s)) and s[i+1] != '\n' else '' #3
' '
或''
添加到字符串的开头。我们检查以前的字符s[i-1]
是否不是换行符\n
。我们还必须检查索引是否为((i-1) > 0
)char
如果特殊字符位于字符串的末尾(或在开头),这也将不添加空格。如果您希望这种情况发生,您必须稍微修改条件。
我做了其他一些改动:
s
,因为string
是类to_return
初始化为一个空列表,该列表将附加到enumerate(s)
(而不是to_return
),因为当您修改正在迭代的对象时可能会发生错误的事情in {set}
代替单独检查所有字符答案 3 :(得分:1)
你不必扫描&#34;对于换行符,只要您在当前字符之前或之后存在不是空格的字符时添加空格。
我不认为可以用一个正则表达式完成,但有两个你可以在需要的地方添加空格。它需要两个 lookbehinds / lookaheads,因为有两个条件:
@
,#
或?
之前/之后必须至少有一个字符; 我为了一致性添加了第三个条件:
因此,当已经存在空间时,不会添加空间。 (这只是一个方便的补充,因为\S
碰巧匹配&#34;所有不像空格的东西&#34;。)
为什么你需要两个lookbehinds?因为如果有一个角色(不能是类似空格),其中一个将匹配,而如果有一个角色,则另一个将匹配,而不是&#34;换行符,包括字符串本身的开头和结尾。
以下代码,稍微修改一下输入字符串以显示它在边缘情况下的作用,
import re
str = '@0x0D?0A\n@0x1f?@0x2f?48# 65#6C#6C#6F#2C#20#57#6F#72#6C#64#21@'
str = re.sub(r'(?<=\S)(?<!\n)([@?#])', r' \1', str)
str = re.sub(r'([@?#])(?!\n)(?=\S)', r'\1 ', str)
print ('"'+str+'"')
结果
"@ 0x0D ? 0A
@ 0x1f ? @ 0x2f ? 48 # 65 # 6C # 6C # 6F # 2C # 20 # 57 # 6F # 72 # 6C # 64 # 21 @"
其中双引号仅添加到显示结果字符串的开头和结尾。