2

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

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

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

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 个字符的终端不匹配,但该示例是说明性的。

4

2 回答 2

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 "[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.

希望这可以帮助!

于 2012-12-27T17:22:06.443 回答
1

如果脚本名称 is_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
于 2012-12-27T16:25:20.280 回答