我有兴趣编写一个 bash 函数来打印变量的内容并突出显示与给定模式匹配的所有行。
以下用于awk
处理变量中的行。但这不适用于匹配模式,而是通过指定要着色的行(例如 lseq="2,3,5")。
aid ()
{
local -r sgr="$( tput sgr0 )"
local -r blu="$( tput bold; tput setaf 39 )"
awk -v frg="$blu" -v rst="$sgr" -v lnum="$lseq" ptrn="$rl" \
'BEGIN { split(lnum, laggr, ",") }
{
found = 0
for (item in laggr) {
if (laggr[item] == NR) { found = 1 ; break }
}
if (found) { print frg $0 rst }
else { print $0 }
}' <<< "$@"
}
例如,我有以下多行变量,我想在其中打印以edvart
使用蓝色前景开头的行。
rl="^[[:space:]]*edvart .*$"
var="
Here is an example
edvart -W
Some description
Introduction
Menu
Interactive"
答案1
以下是解决该问题的主要要素:
- 用于
tput
着色 - 将源文本放入管道中
- 处理线条
while
这是使用/ 的解决方案read
rst=$( tput sgr0 ) ; hi=$( tput bold; tput setaf 39 )
printf '%s\n' "$source" \
| while read line
do
if [[ "$line" =~ "$pattern" ]]; then
printf '%s\n' "${hi}${line}${rst}"
else
printf '%s\n' "$line"
fi
done
请注意,该=~
语法特定于 bash。可以grep
在 if 语句中使用它并利用其退出状态,但我不会在这里显示这一点,因为您用“bash”标记了问题。
这是一个解决方案awk
:
rst=$( tput sgr0 ) ; hi=$( tput bold; tput setaf 39 )
printf '%s\n' "$source" \
| awk '{
if ( $0 ~ /'"$pattern"'/ ) {
printf "'${hi}'%s'${rst}'\n", $0
} else {
print
}
}'
另一个解决方案是sed
:
rst=$( tput sgr0 ) ; hi=$( tput bold; tput setaf 39 )
printf '%s\n' "$source" | sed "/$pattern/s/^.*$/${hi}&${rst}/"
对于awk
和sed
,我在技术上将颜色/格式嵌入到 awk/sed 脚本中。所以实际上不需要hi
和变量。rst
但我认为它更容易阅读。
awk
和解决方案sed
比 解决方案更具可移植性read
,可在任何 POSIX 兼容系统上运行。
如果您只想突出显示匹配的字符串而不是整行,我建议使用sed
.
rst=$( tput sgr0 ) ; hi=$( tput bold; tput setaf 39 )
printf "$source" | sed "s/$pattern/${hi}&${rst}/g"