我希望从文件中打印一个中间部分(开始模式和结束模式之间),并对特定的行进行着色。
下面是一个这样的文件中的一个示例文本
## 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的输入字符串为
Some information.
Some other text.
Blu:
Some text in blue.下面是捕获中间区域的awk脚本
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。
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 }
}
}发布于 2023-03-09 23:31:17
由于没有一个最小的完整代码示例,也没有足够的示例输入/输出来进行测试,这显然只是一个未经测试的猜测,但看起来您应该更改如下:
display { print }至
display { rec = rec $0 ORS }和
$0 ~ end_ere { display = 0 ; next }至
$0 ~ end_ere { luciferin(rec); rec = ""; display = 0 ; next }或类似和调整luciferin,以删除额外的尾随换行符,从它的arg在打印之前。
关于如何改进问题和操作操作问题--下面是一个完整的、最小的代码示例在这样的问题中的样子:
$ 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]
}
}以及一些示例输入来演示您的需求,并使用以下方法进行测试:
$ 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而预期产出则是这样的投入:
Luci: ## Some information.
Luci: ## Some other text.
Luci: ## Some other information.
Luci: ## Even more text.您的真正代码进行着色或其他任何操作都与您需要帮助的问题完全无关,这就是如何存储一个文本块并调用luciferin()以某种方式修改它。
给出这样一个清晰、简单的例子,我们可以非常迅速地向您展示解决方案,例如:
$ 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]
}
}$ awk -f tst.awk input
Luci: ## Some information.
Luci: ## Some other text.
Luci: ## Some other information.
Luci: ## Even more text.然后你就可以把它的概念应用到你的真实代码中。
发布于 2023-03-09 16:52:06
在awk中解决这个问题当然是可行的,但是你似乎对自己太苛刻了。Perl为这些范围提供了语言支持,它是从注释中提到的sed特性复制而来的。
让我们把春天的月份染成蓝色。
$ cat months.txt | perl -ane 'print "blue" if /Mar/../May/; print "\t$_"'
January
February
blue March
blue April
blue May
June在这些正则表达式中使用FAML / ASMB关键字来使其适应您的用例。
即使你想做比这更好的处理,它仍然是你的管道的一个良好的初始阶段。
现在,后续阶段不必担心行范围;它可以使用第一个字段来确定我们是否在范围内,然后相应地处理行的其余部分。
https://unix.stackexchange.com/questions/739179
复制相似问题