在终端输出周围创建星号边框?
Create asterisk border around output in terminal?
我需要在终端中的命令输出周围创建一个边框,例如,如果命令的输出是这样的:
Apple
Paper Clip
Water
会变成这样:
/==========\
|Apple |
|Paper Clip|
|Water |
\==========/
提前感谢您的所有回复。
-C.L
awk 似乎是最不疯狂的方法:
command | expand | awk 'length([=10=]) > length(longest) { longest = [=10=] } { lines[NR] = [=10=] } 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([=11=]) > length(longest) { # Remember the longest line
longest = [=11=]
}
{ # also remember all lines in order
lines[NR] = [=11=]
}
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.
}
最 疯狂的方法,我敢说你对此有异议,是用 sed:
#!/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/ {
s///
ba
}
//! {
s/\n=*//
ta
}
# build top bit, print it
s,.*,/&\,
p
# build measuring stick
s,.\(.*\).,=,
# for all lines in the output:
:lineloop
# fetch the line
G
s/^\(=*\n\)\([^\n]*\).*//
# replace it with = to get a second measuring stick
s/[^\n]/=/g
# fetch another copy of the line
G
s/^\(=*\n=*\n\)\([^\n]*\).*//
# inner loop:
:spaceloop
# while the line measuring stick is not as long as the overall measuring
# stick
/^\(=*\)\n/! {
# 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\(.*\)/\n/
# 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
。但只做一次以确认它有效。您不想 运行 在生产中使用类似的东西。
不是您要找的语言,但简洁易读:
#!/usr/bin/env ruby
input = STDIN.read.split("\n")
width = input.map(&:size).max + 2
bar = '='*(width-2)
puts '/' + bar + '\'
input.each {|i| puts "|"+i+" "*(width-i.size-2)+"|" }
puts '\'+ bar + '/'
您可以将其保存在一个文件中,chmod +x
它,然后将您的输入输入其中。
如果你"need"将它放在一行中:
echo e"Apple\nPaper Clip\nWater" |
ruby -e 'i=STDIN.read.split("\n");w=i.map(&:size).max+2;b="="*(w-2);i.map! {|j| "|"+j+" "*(w-j.size-2)+"|" };i.unshift "/"+b+"\"; i<<"\"+b+"/";puts i'
我需要在终端中的命令输出周围创建一个边框,例如,如果命令的输出是这样的:
Apple
Paper Clip
Water
会变成这样:
/==========\
|Apple |
|Paper Clip|
|Water |
\==========/
提前感谢您的所有回复。
-C.L
awk 似乎是最不疯狂的方法:
command | expand | awk 'length([=10=]) > length(longest) { longest = [=10=] } { lines[NR] = [=10=] } 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([=11=]) > length(longest) { # Remember the longest line
longest = [=11=]
}
{ # also remember all lines in order
lines[NR] = [=11=]
}
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.
}
最 疯狂的方法,我敢说你对此有异议,是用 sed:
#!/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/ {
s///
ba
}
//! {
s/\n=*//
ta
}
# build top bit, print it
s,.*,/&\,
p
# build measuring stick
s,.\(.*\).,=,
# for all lines in the output:
:lineloop
# fetch the line
G
s/^\(=*\n\)\([^\n]*\).*//
# replace it with = to get a second measuring stick
s/[^\n]/=/g
# fetch another copy of the line
G
s/^\(=*\n=*\n\)\([^\n]*\).*//
# inner loop:
:spaceloop
# while the line measuring stick is not as long as the overall measuring
# stick
/^\(=*\)\n/! {
# 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\(.*\)/\n/
# 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
。但只做一次以确认它有效。您不想 运行 在生产中使用类似的东西。
不是您要找的语言,但简洁易读:
#!/usr/bin/env ruby
input = STDIN.read.split("\n")
width = input.map(&:size).max + 2
bar = '='*(width-2)
puts '/' + bar + '\'
input.each {|i| puts "|"+i+" "*(width-i.size-2)+"|" }
puts '\'+ bar + '/'
您可以将其保存在一个文件中,chmod +x
它,然后将您的输入输入其中。
如果你"need"将它放在一行中:
echo e"Apple\nPaper Clip\nWater" |
ruby -e 'i=STDIN.read.split("\n");w=i.map(&:size).max+2;b="="*(w-2);i.map! {|j| "|"+j+" "*(w-j.size-2)+"|" };i.unshift "/"+b+"\"; i<<"\"+b+"/";puts i'