regex - 我知道正确的正则表达式不适用于 awk。请指教
问题描述
跟进@dawg对我的问题如何根据已知模式删除文件中的多个部分的回答,我想在 awk 中使用正则表达式来标识我要删除的部分的开头。我正在使用的文件是一个 xml 文件。它实际上是包含 Linux Mint 中最近使用的文件名列表 (RUFL) 的文件 (~/.local/share/recently-used.xbel)。这就是RUFL的结构:
<?xml version="1.0" encoding="UTF-8"?>
<xbel version="1.0"
xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"
xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"
>
<bookmark href="file:///home/ocor61/Documents/Linux/Linux%20Mint%20Cinnamon%20Keyboard%20Shortcuts.pdf" added="2021-07-18T01:57:02Z" modified="2021-07-18T01:57:02Z" visited="1969-12-31T23:59:59Z">
<info>
<metadata owner="http://freedesktop.org">
<mime:mime-type type="application/pdf"/>
<bookmark:applications>
<bookmark:application name="Document Viewer" exec="'xreader %u'" modified="2021-07-18T01:57:02Z" count="1"/>
</bookmark:applications>
</metadata>
</info>
</bookmark>
<bookmark href="file:///home/ocor61/Documents/Linux/Linux%20Command%20Line%20Cheat%20Sheet.pdf" added="2021-07-18T01:57:09Z" modified="2021-07-18T01:57:09Z" visited="1969-12-31T23:59:59Z">
<info>
<metadata owner="http://freedesktop.org">
<mime:mime-type type="application/pdf"/>
<bookmark:applications>
<bookmark:application name="Document Viewer" exec="'xreader %u'" modified="2021-07-18T01:57:09Z" count="1"/>
</bookmark:applications>
</metadata>
</info>
</bookmark>
<bookmark href="file:///home/ocor61/Documents/work.bfproject" added="2021-07-20T10:52:59Z" modified="2021-07-22T08:41:57Z" visited="1969-12-31T23:59:59Z">
<info>
<metadata owner="http://freedesktop.org">
<mime:mime-type type="application/x-bluefish-project"/>
<bookmark:applications>
<bookmark:application name="bluefish" exec="'bluefish %u'" modified="2021-07-22T08:41:57Z" count="2"/>
</bookmark:applications>
</metadata>
</info>
</bookmark>
</xbel>
我正在编写一个脚本以从列表中删除文件名。它工作正常,但我也在使用一个包含不应使用的模式的数组。例如:如果模式 [bookmark] 将用于标识必须删除的部分,则整个文件将变得不可用。这适用于 [书签] 的部分内容,也适用于 href、added、info... 你明白我的意思。
因此,我想使用正则表达式来解决输入无法使用的模式的问题。
目前,这是我现在使用的 awk 代码(感谢@dawg):
ENDLINE='</bookmark>'
awk -v f=1 -v st="$1" -v end="$ENDLINE" '
match($0, st) {f=0}
f
match($0, end){f=1}' ~/.local/share/recently-used.xbel
$1 将是用户在命令行输入的模式,它是必须从 RUFL 中删除的文件名的一部分。
以下是我想使用的代码,包括不起作用的正则表达式:
STARTLINE='/(<bookmark href)(.*)($1)(.*)(>)/'
ENDLINE='</bookmark>'
awk -v f=1 -v st="$STARTLINE" -v end="$ENDLINE" '
match($0, st) {f=0}
f
match($0, end){f=1}' ~/.local/share/recently-used.xbel
我已经在https://regexr.com/测试了正则表达式,所以我知道它是正确的。但是,当我在脚本中使用它时,这是我收到的错误消息:
./ruffle.sh: line 99: syntax error near unexpected token `$0,'
./ruffle.sh: line 99: ` match($0, st) {f=0}'
我也尝试在 awk 命令行而不是变量中输入正则表达式本身,但结果相同。
我不知道如何继续,所以任何帮助表示赞赏。
解决方案
我的问题的答案在于正则表达式在不同环境中使用时会有什么不同。我用来检查我的正则表达式的网站对于 JS 等语言是这样做的,但对于 Bash 或其他可能的 shell 实现则不然。使用 shellcheck.net 以及将命令“set -vx”放在我的脚本中,就在 awk 命令之前,我设法解决了问题。
我犯的另一个错误是试图捕获正则表达式中的完整行,而我只需要该行中可以保存输入模式的部分(这是文件中“文件:”和“添加”之间的部分~/.local/share/recently-used.xbel)。
现在使用变量 STARTLINE 最终对我有用的正则表达式是:
STARTLINE='file:.*'$1'.*added='
我将不得不考虑使用 xml 解析器,感谢您的建议!但是,目前,我的脚本有效。感谢@Sundeep 和@EdMorton!
推荐阅读
- java - 我写了一个java程序。需要一种打印血红蛋白计数的解决方案
- javascript - 如何将函数传递给 setInterval?
- python - Python字符串格式不正确
- c# - Xamarin.Form 应用程序不想在 Visual Studio 中工作
- node.js - 使用发射器/侦听器处理多个 POST 请求
- python - 在不加载页面的情况下加载 Python 函数
- r - 错误:ggplot2 不知道如何处理 gg/ggplot 类的数据
- python - 如何在 google-colaboratory 上永久上传数据?
- android - 应用程序被杀死后在 Android oreo 中监控信标
- libreoffice-calc - 如何使用 LibreOffice 的 Calc 从网站获取数据?