匹配文本部分

匹配文本部分

我想要进行模式匹配以显示与以下结构匹配的文件中的文本部分。

## DN [Pattern-Matching] glob,regex
## Some text
## More text
## DN [Pattern-Matching] ends here

语法在

## DN [TITLE] KEYWORD[,KEYWORD..]
## Some text
## More text
## DN [TITLE] ends here

其中TITLE在任何标题中,带有关键字(多个关键字用逗号分隔)。

要显示该部分,用户提供TITLEKEYWORD

从以下标签开始

  lab="## DN [Something]"

与我上面完成的模式相匹配。

  if [[ "$lab" =~ ^[[:space:]]*([#;!]+|@c|//)[[:space:]]DN[[:space:]]\[.*\]$ ]]; then

现在我必须匹配附加关键字部分。

对于我想要匹配的最后一部分keyword,keyword

我已经开始这样做了([^,]+)。我的困惑是匹配,keyword此后零个或多个的剩余可能性。

答案1

使用 awk 或 perl 进行文本处理,而不是 bash。

例如使用 awk:

awk '/^[[:blank:]]*##[[:blank:]]+DN[[:blank:]]+\[TITLE\]/ {
       if (p) print;
       p = ! p
     };
     p' input.txt 
## DN [TITLE] KEYWORD[,KEYWORD..]
## Some text
## More text
## DN [TITLE] ends here

顺便说一句,如果您不熟悉 awk,pawk 脚本中分号后面的最后一个测试是否p为真,如果为真则打印当前行 - 它的简写相当于{if (p) print}.简而言之:awk 脚本由一系列“PATTERN ACTION”规则组成,并且 PATTERN 或 ACTION 可以省略。模式是任何评估为真或假的东西。如果省略 PATTERN,则默认值为 true(即 ACTION 将始终被执行)。 ACTION 是要执行的 awk 代码。如果省略 ACTION,则默认为print

或使用 perl:

$ perl -ne 'if (/^\h*##\h+DN\h+\[TITLE\]/) {
              print if $p;
              $p = ! $p
            };
            print if $p' input.txt 
## DN [TITLE] KEYWORD[,KEYWORD..]
## Some text
## More text
## DN [TITLE] ends here

两个脚本的操作方式相同——它们是彼此的直接翻译。

在这两个脚本中,变量p$p对于 perl)被用作切换开关,以便在看到模式时打开和关闭打印。

这两个脚本都需要一些代码重复。切换p(或)的代码块$p必须检查是否p为 true 并打印是否为 true切换p。否则,您想要的块的最后一行将不会被打印,因为p在执行“如果 p 为 true 则打印”测试之前已关闭。

注意:[[:blank:]]表示空格或制表符。 Perl 的\h意思任何水平空白(包括一些 unicode 空白字符,具体取决于区域设置)。实际上,两者对于 ASCII 文本的作用是相同的。


如果您需要测试两个条件,则使用两个变量 - 比如说p1and p2(对于 perl 来说是$p1and )。$p2单独测试它们,并且仅在两者都为真时才打印:例如p1 && p2在 awk 中、print if ($p1 && $p2)在 pe​​rl 中。

Shell 变量可以通过命令行或环境变量(exportbash 中的变量,它将在所有子进程的环境中可用)从 shell 传递到 awk 或 perl。

相关内容