添加到缺少模式的行的末尾

时间:2013-08-28 20:32:26

标签: regex linux bash sed awk

我在CentOS上有一个很长的,维护得不好的bash脚本,有很多使用echo的日志行,其中大约三分之一的日志文件都是在日志文件中。我想修改其余的回声线以便也可以进入这个日志文件。

这是一个示例myscript.sh:

command1
echo "hi1"
echo "hi2" | tee -a my.log
echo "hi3 tee"
command2

在此文件上运行之后,我希望将内容更改为:

command1
echo "hi1" | tee -a my.log
echo "hi2" | tee -a my.log
echo "hi3 tee" | tee -a my.log
command2

我在想我需要在正则表达式中使用sed或awk,其中逻辑是“如果该行包含'echo',则后跟 not '{{ 1}}',然后在行的末尾追加'| tee'。

经过大量的搜索,这是我迄今为止最好的:

| tee -a my.log

但这只会将sed --in-place=_BACKUP '/^.*echo\(?!\| tee$\)*/ s/$/ \| tee -a my.log/' myscript.sh 附加到包含| tee -a my.log的每一行的末尾。

有没有人有什么好主意?

3 个答案:

答案 0 :(得分:3)

这应该是的诀窍(尽管我感觉到了一堆角落的情况)

$ awk '/^echo/&&!/tee -a my.log$/{$0=$0"| tee -a my.log"}1' file
command1
echo "hi1"| tee -a my.log
echo "hi2" | tee -a my.log
echo "hi3 tee"| tee -a my.log
command2

<强>解释

/^echo/                  # If the line start echo
&&                       # Logical AND
!/tee -a my.log$/        # Doesn't end with tee -a my.log
{$0=$0"| tee -a my.log"} # Append the tee command to the end of the line
1                        # Awk idiom to print all the lines in the file

答案 1 :(得分:2)

实际上最好为文件打开fd并使用函数来记录消息,例如。

exec 40>>my.log

function log {
    echo "$1"
    echo "$1" >&40
}

command1
log "hi1"
log "hi2"
log "hi3"
command2

exec 40>&-

您的脚本实际上会以这种方式运行得更快,并且不再需要您继续呼叫tee。

这样的命令可能是将文件转换为:

的开始
sed '/echo /{ s@ \?| \?tee -a my.log@@; s@echo @log @; }' file

答案 2 :(得分:0)

刚学到一点awk并感觉很棒!写了这个并测试了样本输入:

awk '{if ($0 ~ "^echo" && $0 !~ "tee -a") \
        print $0" | tee -a my.log"; \
      else \
        print $0}' myscript.sh

Where
$0    #means the current line of input
~     #match the following regex
!~    #not match the following regex

正如sudo_O所说,可能有许多边缘情况导致程序失败。