【问题标题】:Regex to replace whitespace in Markdown URLs正则表达式替换 Markdown URL 中的空格
【发布时间】:2021-12-18 04:07:17
【问题描述】:

我有一堆带有空格的 Markdown 链接,我需要用 %20 替换空格。到目前为止,我已经破解了一些解决方案,但没有一个可以在 VSCode 中工作,或者完全符合我的要求。

这是我需要的网址格式转换:

[My link](../../_resources/my resource.jpg)
[My link](../../_resources/my%20resource.jpg)

\s+(?=[^(\)]*\)) 将适用于括号内的任何空白 - 但会产生误报,因为它适用于任何带括号的内容。

(?:\]\(|(?!^)\G)[^]\s]*\K\h+ 完成了这项工作,但我在 VSCode 中收到了一些“无效的转义字符”消息,所以我认为该语言不兼容。

我一直在尝试识别字符 ]( 上的链接,但由于我对正则表达式比较陌生,所以有点挣扎。

我尝试使用此正则表达式:(?<=\]\()s\+,因为此(?<=\]\().+ 正确识别了网址,但它不起作用。

我哪里错了?提前致谢!

编辑:文件中的 VSCode 查找不支持可变长度后向查找,即使打开文件中的查找/替换确实支持这一点。在我开始编写脚本之前,请接受任何其他解决方案!

【问题讨论】:

  • 您不能在 VSCode 中使用单个正则表达式传递来做到这一点,因此请使用具有 Boost 正则表达式引擎并提供在文件中查找/替换选项的 Notepad++。正则表达式为(\G(?!\A)|\[[^][]*]\()([^()\s]*)\s+(?=[^()]*\)) 并替换为$1$2%20

标签: regex visual-studio-code


【解决方案1】:

VSCode 正则表达式不支持\K\G\h,但它支持不固定宽度的 Lookbehinds。因此,您可以使用如下内容:

(?<=\]\([^\]\r\n]*)[^\S\r\n]+

Online demo.

【讨论】:

  • 我相信这种模式是不言自明的。如果有不清楚的地方,请告诉我,我会为你分解。
  • 你能用空格字符替换[^\S\r\n]吗(即,如果你不关心制表符、垂直制表符和换页符)?
【解决方案2】:

你可以使用

(?<=\]\([^\]]*)\s+(?=[^()]*\))

替换为%20。查看演示截图:

详情

  • (?&lt;=\]\([^\]]*) - 正向后视,匹配紧接在 ]( 前面的位置,然后是除 ] 之外的任何零个或多个字符
  • \s+ - 任何一个或多个空白字符(Visual Studio Code 中的换行符除外,如果正则表达式中没有 \n\r\s 不匹配换行符)
  • (?=[^()]*\)) - 一个正向前瞻,它与紧随其后的零个或多个字符而不是 () 以及 ) 字符的位置相匹配。

由于您在文件中的查找/替换中使用它,因此这种后视解决方案将不起作用。

您可以将 Notepad++ 与

一起使用
(\G(?!\A)|\[[^][]*]\()([^()\s]*)\s+(?=[^()]*\))

$1$2%20 替换模式。在 Notepad++ 中,按CTRL+SHIFT+F 并在填写完必要的字段后,点击Replace in Files

查看示例设置:

【讨论】:

  • 不知道 VSCode 默认不匹配垂直空白字符。这使得这个答案比我的更好。有我的支持:)
  • @41686d6564 更多,\[[^\]\[]*\] 也不会跨行匹配,因此它也会影响否定字符类。这与 Vim 兼容,尽管此处相似性结束(如在 Vim 中,需要使用 \_ 来启用换行符匹配,而在 VSCode 中,\r\n 必须添加到模式中的任何位置(甚至 \n{0}会做,虽然一般来说没有什么意义)。
  • 感谢大家的回答 - 令人讨厌的是,这适用于文件中的查找替换,但不适用于文件中的查找 (ctrl/cmd-shift-f)。看起来他们正在使用稍微不同版本的正则表达式 - 文件中的查找不支持变量后视。
  • @jt196 是的,它不会因为文件中的查找/替换中的正则表达式引擎使用 Rust 正则表达式引擎。在文档内搜索和替换中不是符合 ECMAScript 2018 的。您需要在 Notepad++ 中使用正则表达式替换文件功能。
  • SO post 提供更多信息。
【解决方案3】:

最后,由于我在 Mac 上并且不想启动虚拟 PC 来运行 Notepad++(Sublime 使用相同的引擎,Atom 不允许您排除文件),我使用了组合一个 Python 脚本,带有 @Wiktor Stribizew 的答案,用于处理由于某种原因而未被模式拾取的单个文件。

md_url_pattern = r'(\[(.+)\])\(([^\)]+)\)'

def remove_spacing(match_obj):
    if match_obj.group(3) is not None:
        print("Match Object: " + match_obj.group(1) + "(" + re.sub(r"\s+", "%20", match_obj.group(3)) + ")")
        return match_obj.group(1) + "(" + re.sub(r"\s+", "%20", match_obj.group(3)) + ")"

# THIS_FOLDER = os.path.dirname(os.path.abspath(__file__))
this_folder = '<my_document_folder>' # fixed folder path
note_path = '<note_folder>' # change this 
full_path = os.path.join(this_folder, note_path)
directory = os.listdir(full_path)
os.chdir(full_path)

for file in directory:
    open_file = open(file, 'r')
    read_file = open_file.read()
    read_file = re.sub(md_url_pattern, remove_spacing, read_file)
    if not read_file:
        print("Empty file!")
    else:
        write_file = open(file,'w')
        write_file.write(read_file)

这个脚本可以做一些整理和调试(奇怪的空文件和不兼容子文件夹),但这是我能做的最好的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 2018-09-19
    • 2013-01-22
    • 2021-08-29
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    相关资源
    最近更新 更多