Python 正则表达式模式,用于查找代码行是否以 space 或制表符结束

Python regex pattern in order to find if a code line is finishing with a space or tab character

很抱歉提出这么低级的问题,但我真的在来这里之前试图寻找答案...... 基本上我有一个脚本,它在 .py 文件中搜索并逐行读取那里的代码 -> 脚本的目标是查找一行是否以 space 或制表符结束,如下例所示

i = 5 
z = 25 

基本上在 i 变量之后我们应该有一个 \s 并且在 z 变量之后有一个 \t 。 (希望代码格式不要抹掉)

def custom_checks(file, rule):
    """
    @param file: file: file in-which you search for a specific character
    @param rule: the specific character you search for
    @return: dict obj with the form { line number : character }
    """
    rule=re.escape(rule)
    logging.info(f"     File {os.path.abspath(file)} checked for {repr(rule)} inside it ")
    result_dict = {}

    file = fileinput.input([file])
    for idx, line in enumerate(file):
        if re.search(rule, line):
            result_dict[idx + 1] = str(rule)

    file.close()
    if not len(result_dict):
        logging.info("Zero non-compliance found based on the rule:2 consecutive empty rows")
    else:
        logging.warning(f'Found the next errors:{result_dict}')

之后,如果我检查日志输出,我会看到: 检查里面的 '\+s\\s\$' 我不知道为什么 \ 是双倍的 基本上我也从 config.json 得到所有的正则表达式,就是这个:

{
  "ends with tab":"+\t$",
  "ends with space":"+s\s$"

}

有人可以在这个方向上帮我吗->我基本上知道我可以用其他方式做,比如反转行 [::-1] 得到第一个字符,看看它是不是 \s 等等,但我真的想用正则表达式来做。 谢谢!

尝试:

rules = {
  'ends with tab': re.compile(r'\t$'),
  'ends with space': re.compile(r' $'),
}

注意:从迭代中获取行时,文件将在每个字符串的末尾留下换行符 ('\n'),正则表达式中的 $ 匹配第一个 newline 之前的位置在字符串中。因此,如果使用正则表达式,则无需显式去除换行符。

if rule.search(line):
    ...

不过,就我个人而言,我会使用 line.rstrip() != line.rstrip('\n') 一次性标记任何类型的尾随空格。

如果要直接检查行尾的特定字符,则需要去除所有换行符,并且需要检查该行是否为空。例如:

char = '\t'
s = line.strip('\n')

if s and s[-1] == char:
    ...

附录 1:从 JSON 配置中读取规则

# here from a string, but could be in a file, of course
json_config = """
{
    "ends with tab": "\t$",
    "ends with space": " $"
}
"""

rules = {k: re.compile(v) for k, v in json.loads(json_config).items()}

附录 2:评论

下面展示了如何注释掉规则,以及检测文件中注释的规则来处理。由于JSON不支持注释,我们可以考虑用yaml代替:

yaml_config = """
ends with space: ' $'
ends with tab: \t$
is comment: ^\s*#
# ignore: 'foo'
"""

import yaml

rules = {k: re.compile(v) for k, v in yaml.safe_load(yaml_config).items()}

注:'is comment'很简单。假设的 'has comment' 更难定义——为什么?我将把它留作 reader 的练习 ;-)

注意 2:在文件中,yaml 配置将没有双反斜杠,例如:

cat > config.yml << EOF
ends with space: ' $'
ends with tab: \t$
is comment: ^\s*#
# ignore: 'foo'
EOF

补充思考

您可能想 autopep8 试一试。

示例:

cat > foo.py << EOF
# this is a comment   

text = """
# xyz  
bar  
"""
def foo(): 
    # to be continued  
    pass 

def bar():
  pass     

 
  
EOF

注意:要显示多余的空格:

cat foo.py | perl -pe 's/$/|/'
# this is a comment   |
|
text = """|
# xyz  |
bar  |
"""|
def foo(): |
    # to be continued  |
    pass |
|
def bar():|
  pass     |
|
 |
  |

上面有几个 PEP8 问题(行尾有额外的空格,函数之间只有 1 行,等等)。 Autopep8 修复了所有问题(但正确地保留了文本变量不变):

autopep8 foo.py | perl -pe 's/$/|/'
# this is a comment|
|
text = """|
# xyz  |
bar  |
"""|
|
|
def foo():|
    # to be continued|
    pass|
|
|
def bar():|
    pass|