Bash:处理日志文件输出的格式

Bash:处理日志文件输出的格式,bash,sed,string-formatting,Bash,Sed,String Formatting,我有一个字符串格式的问题,虽然我知道我想做什么,但我不知道到底怎么做。我希望这里的某个地方能帮上忙。我的问题是这样的: 在我的脚本中,我使用函数编写日志输出,日志输出使用标准化但长度可变的头和用户定义的消息体。消息的长度和终端宽度意味着消息通常会环绕。我想做的是在换行符中插入“padding”,以便消息在日志中显示的格式更高 这里是我工作代码的一部分经过改编的未经测试的摘录。它显示了我想做什么: local __mgs_hdr="[${__DATE}@${__TIME} ${__script}]

我有一个字符串格式的问题,虽然我知道我想做什么,但我不知道到底怎么做。我希望这里的某个地方能帮上忙。我的问题是这样的:

在我的脚本中,我使用函数编写日志输出,日志输出使用标准化但长度可变的头和用户定义的消息体。消息的长度和终端宽度意味着消息通常会环绕。我想做的是在换行符中插入“padding”,以便消息在日志中显示的格式更高

这里是我工作代码的一部分经过改编的未经测试的摘录。它显示了我想做什么:

local __mgs_hdr="[${__DATE}@${__TIME} ${__script}] -> "
local __msg_body="${1}"
local __hdrlen=$(expr length $__msg_hdr)
local __msglen=$(expr length $__msg_body)
local __max_msglen=$(expr 80 - $__hdrlen)
local __line=""

if [ $__msglen -gt $__max_mslen ]; then # we need to format the message
    # Insert newline followed by "$__hdrlen" whitespaces into $__msq_body at $_hdrlen intervals
    # to align/justify log lines as blocks of text for each log header entry
    # Replace the : with a command to format $__line
    :
else
    __line="${__msg_hdr}${__msg_body}"
fi
所以,我有一种方法来确定何时填充一条记录线,我想我可以做到这一点。我只是不知道怎么做。如果有人能给我指出正确的方向,我将不胜感激

下面是一个使用静态格式生成的示例输出。它显示了我想要达到的目标:

[2012-12-27@15:56:43 test.sh] -> Writing a log file entry that 
                                 is wrapped onto the next line 
                                 with appropriate formatting... 

我希望这能让我努力实现的目标更加清晰。行长与80个字符的终端不匹配,但示例是说明性的。

如果脚本名为“a\u really\u long\u name.sh会发生什么

[2012-12-27@15:56:43 is_a_really_long_name.sh] -> Writing a lo
                                                  g file entry 
                                                  that is wrapp
                                                  ed onto the n
                                                  ext line with
                                                  appropriate f
                                                  ormatting...
如果您关心格式化,那么为什么不将头放在一行上,将日志消息格式化在下面的行上呢

[2012-12-27@15:56:43 is_a_really_long_name.sh] ->
Writing a log file entry that is wrapped onto the next line with appropriate
formatting... 

一些代码-前者

#!/bin/bash
headerlen=40
maxlinelen=79
linelen=$maxlinelen-headerlen
spaces="                                                                               "
msg="This is a message that needs to be split into chunks that are the same width. For illustrative purpose only. Your milage mag vary."

msglen=${#msg}
start=0
while [ $start -lt  $msglen ]
do
    echo -n "${spaces:1:$headerlen}"
    echo "${msg:$start:$linelen}"
    let start=$start+$linelen
done
如果你想做后一件事,那么你可以使用类似这样的方法来分割你的消息

#!/bin/bash

linelen=10

msg="This is a message that needs to be split into chunks that are the same width. For illustrative purpose only. Your milage mag vary."

msglen=${#msg}
start=0
while [ $start -lt  $msglen ]
do
    echo "${msg:$start:$linelen}"
    let start=$start+$linelen
done

这里有一个函数可以帮助您(在bash中):

现在,我希望您的消息中不会有任何格式垃圾(例如,颜色代码等),否则此脚本将失败得很惨

它将换行符(在空格处)拆分为单词。正如您将在第一个输出中看到的,如果一行太长而无法容纳,那么它将被放置在自己的一行上(如果可能的话)

<>如果你不在意中间的话,那就容易多了:

print_padded() {
    local header=$1
    local msg=$2
    local width=$3
    local headerlength=${#header}
    local i
    local msgspace=$((width-headerlength))
    (((msgspace<0) && (msgspace=20)))
    printf "%s %s\n" "$header" "${msg:$i:$msgspace}"
    for ((i=msgspace;i<${#msg};i+=msgspace)); do
        printf "%${headerlength}s %s\n" '' "${msg:$i:$msgspace}"
    done
}

希望这有帮助

你最好举一个输入和预期输出的例子,而不是只说你做了什么更新问题…
man printf
。祝你好运。我喜欢你的
空格
变量,但与其说它是一个严肃的解决方案,不如说它是一个肮脏的(容易破坏的)黑客
printf
更合适。另外,
let
已被弃用,请改用shell算法。顺便说一句,shell算法将使您能够以更好的方式在
while
循环中编写测试
:-/
是的,我昨晚考虑了标题长度大于术语宽度的场景。我需要处理这个问题——可能是从加长的标题长度中减去术语宽度。@d_w_r:我花了很多年的时间处理日志文件,老实说,我从来并没有在一行格式上遇到过任何问题。不过,你的“漂亮”日志文件很快就会变得令人恼火,例如,我无法对某个特定术语进行grep,并期望获得与之相关的整个日志条目。这非常有趣,并且会很好地映射到我所做的事情,只需几个mod。谢谢:)
$ # Demo with 40 columns...
$ msg="Writing a log file entry that is wrapped onto the next line with appropriate formatting..."
$ print_padded "[2012-12-27@15:56:43 test.sh] ->" "$msg" 40
[2012-12-27@15:56:43 test.sh] -> Writing
                                 a log
                                 file
                                 entry
                                 that is
                                 wrapped
                                 onto
                                 the
                                 next
                                 line
                                 with
                             appropriate
                           formatting...
$ # Demo with 60 columns:
$ loremipsum="Lorem ipsum dolor sit amet, consectetur adipiscing \
elit. Duis erat purus, vestibulum non sollicitudin ornare, aliquam \
nec mi. In vulputate velit ut felis porta tincidunt. Integer odio \
odio, ullamcorper id ultricies a, fermentum vitae augue. \
Nunc sapien ipsum, dignissim sit amet eleifend eu, suscipit sed eros. \
In hac habitasse platea dictumst. Morbi feugiat interdum ligula \
eu consectetur. Sed congue lacinia felis, a adipiscing nibh \
aliquam in. Vestibulum ante ipsum primis in faucibus orci luctus \
et ultrices posuere cubilia Curae; Proin faucibus ultrices tincidunt."
$ print_padded "loremipsum ->" "$loremipsum" 60
loremipsum -> Lorem ipsum dolor sit amet, consectetur
              adipiscing elit. Duis erat purus, vestibulum
              non sollicitudin ornare, aliquam nec mi. In
              vulputate velit ut felis porta tincidunt.
              Integer odio odio, ullamcorper id ultricies a,
              fermentum vitae augue. Nunc sapien ipsum,
              dignissim sit amet eleifend eu, suscipit sed
              eros. In hac habitasse platea dictumst. Morbi
              feugiat interdum ligula eu consectetur. Sed
              congue lacinia felis, a adipiscing nibh
              aliquam in. Vestibulum ante ipsum primis in
              faucibus orci luctus et ultrices posuere
              cubilia Curae; Proin faucibus ultrices
              tincidunt.
print_padded() {
    local header=$1
    local msg=$2
    local width=$3
    local headerlength=${#header}
    local i
    local msgspace=$((width-headerlength))
    (((msgspace<0) && (msgspace=20)))
    printf "%s %s\n" "$header" "${msg:$i:$msgspace}"
    for ((i=msgspace;i<${#msg};i+=msgspace)); do
        printf "%${headerlength}s %s\n" '' "${msg:$i:$msgspace}"
    done
}
$ # Demo with 40 columns...
$ msg="Writing a log file entry that is wrapped onto the next line with appropriate formatting..."
$ print_padded "[2012-12-27@15:56:43 test.sh] ->" "$msg" 40
[2012-12-27@15:56:43 test.sh] -> Writing 
                                 a log fi
                                 le entry
                                  that is
                                  wrapped
                                  onto th
                                 e next l
                                 ine with
                                  appropr
                                 iate for
                                 matting.
$ # Demo with 60 columns:
$ loremipsum="Lorem ipsum dolor sit amet, consectetur adipiscing \
elit. Duis erat purus, vestibulum non sollicitudin ornare, aliquam \
nec mi. In vulputate velit ut felis porta tincidunt. Integer odio \
odio, ullamcorper id ultricies a, fermentum vitae augue. \
Nunc sapien ipsum, dignissim sit amet eleifend eu, suscipit sed eros. \
In hac habitasse platea dictumst. Morbi feugiat interdum ligula \
eu consectetur. Sed congue lacinia felis, a adipiscing nibh \
aliquam in. Vestibulum ante ipsum primis in faucibus orci luctus \
et ultrices posuere cubilia Curae; Proin faucibus ultrices tincidunt."
$ print_padded "loremipsum ->" "$loremipsum" 60
loremipsum -> Lorem ipsum dolor sit amet, consectetur adipisc
              ing elit. Duis erat purus, vestibulum non solli
              citudin ornare, aliquam nec mi. In vulputate ve
              lit ut felis porta tincidunt. Integer odio odio
              , ullamcorper id ultricies a, fermentum vitae a
              ugue. Nunc sapien ipsum, dignissim sit amet ele
              ifend eu, suscipit sed eros. In hac habitasse p
              latea dictumst. Morbi feugiat interdum ligula e
              u consectetur. Sed congue lacinia felis, a adip
              iscing nibh aliquam in. Vestibulum ante ipsum p
              rimis in faucibus orci luctus et ultrices posue
              re cubilia Curae; Proin faucibus ultrices tinci
              dunt.