AWK кажется, наименее безумным способом идти об этом:
command | expand | awk 'length($0) > length(longest) { longest = $0 } { lines[NR] = $0 } END { gsub(/./, "=", longest); print "/=" longest "=\\"; n = length(longest); for(i = 1; i <= NR; ++i) { printf("| %s %*s\n", lines[i], n - length(lines[i]) + 1, "|"); } print "\\=" longest "=/" }'
expand
заменяет вкладки, которые могут быть на выходе с соответствующим количеством пробелов, чтобы сохранить внешний вид его такой же (чтобы каждый байт вывода отображался с одинаковой шириной). Код AWK работает следующим образом:
length($0) > length(longest) { # Remember the longest line
longest = $0
}
{ # also remember all lines in order
lines[NR] = $0
}
END { # when you have everything:
gsub(/./, "=", longest) # build a line of = as long as the longest
# line
print "/=" longest "=\\" # use it to print the top bit
n = length(longest) # format the content with left and right
for(i = 1; i <= NR; ++i) { # delimiters; spacing through printf
printf("| %s %*s\n", lines[i], n - length(lines[i]) + 1, "|")
}
print "\\=" longest "=/" # print bottom bit.
}
наиболее безумный способ сделать это, и я осмелюсь вам оспаривать это, является с СЭД:
#!/bin/sed -f
# assemble lines in the hold buffer, preceded by the left delimiter
s/^/|/
1h
1!H
$!d
# make a copy of it in the pattern space
x
h
# isolate the longest line (or rather: a line of = as long as the longest
# line)
s/[^\n]/=/g
:a
/^\(=*\)\n\1/ {
s//\1/
ba
}
//! {
s/\n=*//
ta
}
# build top bit, print it
s,.*,/&\\,
p
# build measuring stick
s,.\(.*\).,=\1,
# for all lines in the output:
:lineloop
# fetch the line
G
s/^\(=*\n\)\([^\n]*\).*/\1\2/
# replace it with = to get a second measuring stick
s/[^\n]/=/g
# fetch another copy of the line
G
s/^\(=*\n=*\n\)\([^\n]*\).*/\1\2/
# inner loop:
:spaceloop
# while the line measuring stick is not as long as the overall measuring
# stick
/^\(=*\)\n\1/! {
# append a = to it and a space to the line for output
s/\n/\n=/
s/$//
b spaceloop
}
# once that is done, append the second delimiter
s/$/|/
# remove one measuring stick
s/=*\n//
# put the second behind the actual line
s/\(.*\)\n\(.*\)/\2\n\1/
# print the line
P
# remove it. Only the measuring stick remains and can be reused for the
# next line
s/.*\n//
# do this while there are more lines to be processed
x
/\n/ {
s/[^\n]*\n//
x
b lineloop
}
# then build the bottom bit and print it.
x
s/=/\\/
s/$/\//
Положи в файле foo.sed
, использование command | expand | sed -f foo.sed
. Но сделайте это только один раз, чтобы подтвердить, что он работает. Вы не хотите запускать что-то подобное на производстве.
Является ли это ваша команда, или вы пытаетесь украсить вывод других команд? Пожалуйста, обновите свой вопрос, чтобы включить код, который вы уже пробовали, и объясните, какая часть его дает вам проблемы. –
Я задал аналогичный вопрос некоторое время назад, что могло бы быть актуальным: http://stackoverflow.com/questions/22958873/make-echo-autofill-a-line-of-certain-width – Miguel