【问题标题】:Prepend a String to a Regex Match Using Bash使用 Bash 将字符串添加到正则表达式匹配
【发布时间】:2021-06-30 10:43:50
【问题描述】:

我有一个文件,它的某些行上有一个特定的字符串,采用[Name](./path_to_name_directory)[Name](./path_to_name_directory/notes.md) 的形式,每个都有一些不重要的列表项。对于没有在括号内的文件路径末尾有notes.md 的行,Name 被添加到该行的前面。

为了尝试解决这个问题,我最初有以下命令

sed 's/\[(.*)\]\(\.\/.*\/(?!notes\.md)/\1&/g' ./file.md

但我最终发现 sed 不支持前瞻或后瞻,所以我转而使用 perl 来尝试完成同样的工作。我以为它会像做一样简单

perl -pe 's/\[(.*)\]\(\.\/.*\/(?!notes\.md)/\1&/g'

但它不起作用,我不完全确定从这里去哪里。

编辑 1:

示例输入文件:

- [Name 1](./path_to_name_1)
  - Unimportant list item.
- [Name 2](./path_to_name_2/notes.md)
  - Unimportant list item.

示例输出文件:

- Name 1 [Name 1](./path_to_name_1)
  - Unimportant list item.
- [Name 2](./path_to_name_2/notes.md)
  - Unimportant list item.

【问题讨论】:

  • 请提供示例输入文件和所需的输出。
  • stackoverflow.com/questions/9053100/… 查看此答案作为解决方法:您可以使用 sed 规则来匹配以“notes.md”结尾且不执行任何操作的行,以及匹配剩余内容并执行某些操作的规则.
  • @Shawn,抱歉。我在编辑中添加了示例输入和示例输出。
  • @Kalcifer,我会要求您在答案中添加您的代码(您提出的),是的,提问者也可以回答他们的问题。通过这样做,您可以保持您的问题清晰(您可以编辑您的问题并使其与被询问的方式相似以避免混淆;因为有一个可用的答案部分),谢谢。

标签: regex perl awk sed


【解决方案1】:

使用awk,您可以将FS 设置为[][]|/|)。这样就可以得到$2$5的内容,并放入条件。

awk -v FS='[][]|/|)' '$2 ~ /^Name [[:digit:]]/ && $5 !~ /notes.md/ {sub(/^. /, "&"$2" " , $0)} 1' file
- Name 1 [Name 1](./path_to_name_1)
  - Unimportant list item.
- [Name 2](./path_to_name_2/notes.md)
  - Unimportant list item.

【讨论】:

    【解决方案2】:

    我使用@ RavinderSingh13's answerthis 相关答案提出的一个选项如下

    sed -E '/.*notes\.md.*/!s/\[(.*)\]/\1&/g'
    

    /.*notes\.md.*/! 告诉sed 如果字符串与该正则表达式匹配,则不匹配。换句话说,sed 只会匹配与地址规范不匹配的行(参见 GNU Sed 手册的 section 4.1 的代码块 #5)。

    s/\[(.*)\]/\1&/g 告诉sed 捕获方括号的内部字符串并将其添加到整个匹配项之前;完成位置放置的正则表达式部分是\1&,其中\1 是捕获组,& 引用字符串的整个匹配部分。)

    【讨论】:

      【解决方案3】:

      使用您展示的示例,请尝试以下操作。

      awk '
      !/notes\.md\)$/ && match($0,/\[Name [0-9]+/){
        $1=$1 OFS substr($0,RSTART+1,RLENGTH-1)
      }
      1
      ' Input_file
      

      说明:为上述添加详细说明。这仅用于解释目的。

      awk '
      ##Starting awk program from here.
      !/notes\.md\)$/ && match($0,/\[Name [0-9]+/){
      ##Checking condition if current does not end with notes.md) then match [Name digits in current line.
        $1=$1 OFS substr($0,RSTART+1,RLENGTH-1)
      ##Re-create 1st field which has current $1 OFS and sub string of matched regex value.
      }
      1
      ##This will print current edited/non-edited line here.
      ' Input_file ##Mentioning Input_file name here.
      

      【讨论】:

      • 带来了类似的东西,但你更快 :-) 不知道 1 独自站在打印线。
      • @LudovicKuty,谢谢 :) 是的 1 在 awk 中打印行,这是打印当前行的最简单方法,干杯
      • 当我阅读stackoverflow.com/a/24643330/452614 时,一切都变得清晰起来。应该考虑一下。
      猜你喜欢
      • 2017-08-01
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-30
      相关资源
      最近更新 更多