首页 > 解决方案 > 我知道正确的正则表达式不适用于 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="&apos;xreader %u&apos;" 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="&apos;xreader %u&apos;" 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="&apos;bluefish %u&apos;" 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 命令行而不是变量中输入正则表达式本身,但结果相同。

我不知道如何继续,所以任何帮助表示赞赏。

标签: regexshellawk

解决方案


我的问题的答案在于正则表达式在不同环境中使用时会有什么不同。我用来检查我的正则表达式的网站对于 JS 等语言是这样做的,但对于 Bash 或其他可能的 shell 实现则不然。使用 shellcheck.net 以及将命令“set -vx”放在我的脚本中,就在 awk 命令之前,我设法解决了问题。

我犯的另一个错误是试图捕获正则表达式中的完整行,而我只需要该行中可以保存输入模式的部分(这是文件中“文件:”和“添加”之间的部分~/.local/share/recently-used.xbel)。

现在使用变量 STARTLINE 最终对我有用的正则表达式是:

STARTLINE='file:.*'$1'.*added='

我将不得不考虑使用 xml 解析器,感谢您的建议!但是,目前,我的脚本有效。感谢@Sundeep 和@EdMorton!


推荐阅读