2012-12-27 46 views
2

我有一个字符串格式化问题,虽然我知道我想要做什么,但我不确定如何。我希望在这里的某个地方可以帮助。我的问题看起来像这样:Bash:处理日志文件输出的格式化

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

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

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能做到这一点。我只是不知道如何。如果任何人都可以指引我正确的方向,我会感激。

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

[[email protected]:56:43 test.sh] -> Writing a log file entry that 
           is wrapped onto the next line 
           with appropriate formatting... 

我希望这使得我试图做得更清楚一些。该行长度与80个字符的终端不匹配,但该示例是说明性的。

+0

你最好用你的输入和你的期望输出的例子,而不是只说你做了什么 – Rubens

+0

更新问题... –

+0

'man printf'。祝你好运。 – shellter

回答

1

如果脚本名称is_a_really_long_name.sh会发生什么?

[[email protected]: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... 

如果你关心格式化,那么为什么不只是有一个行和下面

[[email protected]: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 
+0

我喜欢你的'空格'变量,但它比一个严肃的解决方案更肮脏(而且易碎)。 'printf'更合适。此外,'let'已弃用,请使用shell算法。顺便提一句,shell算法将使您能够以更好的方式在'while循环中编写测试。 ': - /' –

+0

是的,我想到了标题长度超过昨晚宽度的场景。我需要处理这个问题 - 可能是从延长的头部长度中减去术语宽度。 –

+0

@d_w_r:我花了很多年处理日志文件,说实话,我从来没有真正遇到过一行格式化问题。尽管你的'漂亮'日志文件很快会变得令人不快,例如我无法理解某个特定的术语,并希望得到与之相关的整个日志条目。 – Iain

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 
} 

然后为使用,例如,

$ # Demo with 40 columns... 
$ msg="Writing a log file entry that is wrapped onto the next line with appropriate formatting..." 
$ print_padded "[[email protected]:56:43 test.sh] ->" "$msg" 40 
[[email protected]: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 "[[email protected]:56:43 test.sh] ->" "$msg" 40 
[[email protected]: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. 

希望这有助于!

+0

这是非常interesing,并将映射很好,与几个mods,我一直在做什么。谢谢:) –