首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >捕获由开始和结束模式定义的多行区域

捕获由开始和结束模式定义的多行区域
EN

Unix & Linux用户
提问于 2023-03-09 11:41:07
回答 2查看 78关注 0票数 1

我希望从文件中打印一个中间部分(开始模式和结束模式之间),并对特定的行进行着色。

下面是一个这样的文件中的一个示例文本

代码语言:javascript
复制
## Beginning of file

Some text and code

## FAML [ASMB] KEYWORD
##  Some information.
##  Some other text.
##  Blu:
##  Some text in blue.
## END OF FAML [ASMB]

## Other text

More text and code

## FAML [ASMB] KEYWORD## END OF FAML [ASMB]之间的文本将被提取(没有开头的##)并传递给函数luciferin,后者将适当地打印多行文本。

块之间的文本被丢弃。后续块的工作原理相同,通过调用函数luciferin(rec)提取和打印中间区域。函数luciferin完成输出的颜色。

luciferin的输入字符串为

代码语言:javascript
复制
Some information.
Some other text.
Blu:
Some text in blue.

下面是捕获中间区域的awk脚本

代码语言:javascript
复制
BEGIN {
  beg_ere = "## [[:alnum:]]+ [[][[:alnum:]]+[]]"
  end_ere = "## END OF [[:alnum:]]+ [[][[:alnum:]]+[]]"
 }

match($0, beg_ere, paggr) { display = 1 }
$0 ~ end_ere { display = 0 ; next }
display { print }

下面是luciferin函数,它接受一个字符串作为输出的颜色。其中cpt在颜色转义序列中,而astr[i]是多行输入字符串的特定行i

代码语言:javascript
复制
function luciferin(mstr) {
  cpt = tseq["Grn:"]
  nlines = split(mstr, astr, "\n")
  for (i = 1; i <= nlines; i++) {
    for ( knam in tseq ) {
      if ( knam == astr[i] ) { cpt = tseq[knam] ; break }
     }
    if (knam == str) { print "" } else { print cpt astr[i] rst }
   }

 }
EN

回答 2

Unix & Linux用户

回答已采纳

发布于 2023-03-09 23:31:17

由于没有一个最小的完整代码示例,也没有足够的示例输入/输出来进行测试,这显然只是一个未经测试的猜测,但看起来您应该更改如下:

代码语言:javascript
复制
display { print }

代码语言:javascript
复制
display { rec = rec $0 ORS }

代码语言:javascript
复制
$0 ~ end_ere { display = 0 ; next }

代码语言:javascript
复制
$0 ~ end_ere { luciferin(rec); rec = ""; display = 0 ; next }

或类似和调整luciferin,以删除额外的尾随换行符,从它的arg在打印之前。

关于如何改进问题和操作操作问题--下面是一个完整的、最小的代码示例在这样的问题中的样子:

代码语言:javascript
复制
$ cat tst.awk
$2 == "FAML" { display = 1 ; next }
$2 == "END" { display = 0 ; next }
display { print }

function luciferin(mstr) {
    nlines = split(mstr, astr, "\n")
    for (i = 1; i <= nlines; i++) {
        print "Luci:", astr[i]
    }
}

以及一些示例输入来演示您的需求,并使用以下方法进行测试:

代码语言:javascript
复制
$ cat input
## Beginning of file

Some text and code

## FAML [ASMB] KEYWORD
##  Some information.
##  Some other text.
## END OF FAML [ASMB]

## Other text

## FAML [ASMB] KEYWORD
##  Some other information.
##  Even more text.
## END OF FAML [ASMB]

More text and code

而预期产出则是这样的投入:

代码语言:javascript
复制
Luci: ##  Some information.
Luci: ##  Some other text.
Luci: ##  Some other information.
Luci: ##  Even more text.

您的真正代码进行着色或其他任何操作都与您需要帮助的问题完全无关,这就是如何存储一个文本块并调用luciferin()以某种方式修改它。

给出这样一个清晰、简单的例子,我们可以非常迅速地向您展示解决方案,例如:

代码语言:javascript
复制
$ cat tst.awk
$2 == "FAML" { display = 1 ; next }
$2 == "END" { luciferin(rec); rec = ""; display = 0 ; next }
display { rec = rec $0 ORS }

function luciferin(mstr) {
    nlines = split(mstr, astr, "\n")
    for (i = 1; i < nlines; i++) {
        print "Luci:", astr[i]
    }
}
代码语言:javascript
复制
$ awk -f tst.awk input
Luci: ##  Some information.
Luci: ##  Some other text.
Luci: ##  Some other information.
Luci: ##  Even more text.

然后你就可以把它的概念应用到你的真实代码中。

票数 1
EN

Unix & Linux用户

发布于 2023-03-09 16:52:06

awk中解决这个问题当然是可行的,但是你似乎对自己太苛刻了。Perl为这些范围提供了语言支持,它是从注释中提到的sed特性复制而来的。

让我们把春天的月份染成蓝色。

代码语言:javascript
复制
$ cat months.txt | perl -ane 'print "blue" if /Mar/../May/; print "\t$_"'
        January
        February
blue    March
blue    April
blue    May
        June

在这些正则表达式中使用FAML / ASMB关键字来使其适应您的用例。

即使你想做比这更好的处理,它仍然是你的管道的一个良好的初始阶段。

现在,后续阶段不必担心行范围;它可以使用第一个字段来确定我们是否在范围内,然后相应地处理行的其余部分。

票数 1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/739179

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档