我想要进行模式匹配以显示与以下结构匹配的文件中的文本部分。
## 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在任何标题中,带有关键字(多个关键字用逗号分隔)。
要显示该部分,用户提供TITLE
或KEYWORD
。
从以下标签开始
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,p
awk 脚本中分号后面的最后一个测试是否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 文本的作用是相同的。
如果您需要测试两个条件,则使用两个变量 - 比如说p1
and p2
(对于 perl 来说是$p1
and )。$p2
单独测试它们,并且仅在两者都为真时才打印:例如p1 && p2
在 awk 中、print if ($p1 && $p2)
在 perl 中。
Shell 变量可以通过命令行或环境变量(export
bash 中的变量,它将在所有子进程的环境中可用)从 shell 传递到 awk 或 perl。