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

时间:2012-12-27 15:18:25

标签: bash sed string-formatting

我有一个字符串格式化问题,虽然我知道我想做什么,但我不确定如何。我希望这里的某处可以提供帮助。我的问题看起来像这样:

在我的脚本中,我使用函数来编写日志输出,该输出使用标准化但可变长度的标题和用户定义的消息体。消息的长度和终端宽度意味着消息经常环绕。我想要做的是在包装的行中插入“填充”,以便消息在日志中显示更多格式。

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

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

所以,我有一种确定何时填充日志行的方法,我认为sed可以做到这一点。我只是不知道如何。如果有人能指出我正确的方向,我会很感激。

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

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

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

2 个答案:

答案 0 :(得分:1)

如果脚本名称为_a_really_long_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

答案 1 :(得分:1)

这是一个可以帮助你(在bash中)的功能:

print_padded() {
    local header=$1
    local msg=( $2 )
    local width=$3
    local headerlength=${#header}
    local i=0
    local spaceleft=$((width-headerlength))
    local defaultspace=20
    (((spaceleft<0) && (spaceleft=defaultspace)))
    local buf=()
    local s
    printf "%s" "$header"
    while ((i<${#msg[@]})); do
       if ((${#msg[i]}+1<=spaceleft)); then
          printf " %s" "${msg[i]}"
          ((spaceleft-=${#msg[i++]}+1))
       else
          echo
          (((spaceleft=width-headerlength)<0 && (spaceleft=defaultspace)))
          while ((${#msg[i]}>=spaceleft)); do
             (((s=width-${#msg[i]})<0 && (s=0)))
             printf "%${s}s%s\n" '' "${msg[i++]}"
          done
          printf "%${headerlength}s" ''
       fi
    done
    echo
}

然后使用as,例如,

$ # 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.

希望这有帮助!