缩进长行标准输出
Indent long line stdout
假设我有一个标准的 80 列终端,执行带有长行输出的命令(即来自 ls
的标准输出)分成两行或更多行,并且想要缩进我所有 bash标准输出。
缩进应该是可配置的,1 或 2 或 3 或任何空格。
由此
lrwxrwxrwx 1 root root 24 Feb 19 1970 sdcard -> /storage/emula
ted/legacy/
至此
lrwxrwxrwx 1 root root 24 Feb 19 1970 sdcard -> /storage/emula
</code> <code>
ted/legacy/
阅读此 Indenting multi-line output in a shell script 所以我尝试使用管道 | sed 's/^/ /'
但给了我完全相反的结果,缩进了第一行而不是后续行。
理想情况下,我会在 profile.rc 或其他任何地方放置一个脚本,这样每次我打开交互式 shell 并执行任何命令时,长输出都会缩进。
一种可能的解决方案是使用纯 bash 字符串操作。
您可以使脚本读取 stdin
并格式化它读取的任何内容。
MAX_LEN=5 # length of the first/longest line
IND_LEN=2 # number of indentation spaces
short_len="$((MAX_LEN-IND_LEN))"
while read line; do
printf "${line:0:$MAX_LEN}\n"
for i in $(seq $MAX_LEN $short_len ${#line}); do
printf "%*s${line:$i:$short_len}\n" $IND_LEN
done
done
用法:(假设脚本保存为indent.sh
)
$ echo '0123456789' | ./indent.sh
01234
567
89
为此我会使用 awk。
awk -v width="$COLUMNS" -v spaces=4 '
BEGIN {
pad = sprintf("%*s", spaces, "") # generate `spaces` spaces
}
NF { # if current line is not empty
while (length > width) { # while length of current line is greater than `width`
print substr([=10=], 1, width) # print `width` chars from the beginning of it
[=10=] = pad substr([=10=], width + 1) # and leave `pad` + remaining chars
}
if ([=10=] != "") # if there are remaining chars
print # print them too
next
} 1' file
一行:
awk -v w="$COLUMNS" -v s=4 'BEGIN{p=sprintf("%*s",s,"")} NF{while(length>w){print substr([=11=],1,w);[=11=]=p substr([=11=],w+1)} if([=11=]!="") print;next} 1'
正如@Mark 在评论中建议的那样,您可以将其放入函数中并将其添加到 .bashrc
以便于使用。
function wrap() {
awk -v w="$COLUMNS" -v s=4 'BEGIN{p=sprintf("%*s",s,"")} NF{while(length>w){print substr([=12=],1,w);[=12=]=p substr([=12=],w+1)} if([=12=]!="") print;next} 1'
}
用法:
ls -l | wrap
Ed Morton 根据要求编辑:
与上面的 oguzismails 脚本非常相似,但应该与 Busybox 或任何其他 awk 一起使用:
$ cat tst.awk
BEGIN { pad = sprintf("%" spaces "s","") }
{
while ( length([=14=]) > width ) {
printf "%s", substr([=14=],1,width)
[=14=] = substr([=14=],width+1)
if ( [=14=] != "" ) {
print ""
[=14=] = pad [=14=]
}
}
print
}
$
$ echo '123456789012345678901234567890' | awk -v spaces=3 -v width=30 -f tst.awk
123456789012345678901234567890
$ echo '123456789012345678901234567890' | awk -v spaces=3 -v width=15 -f tst.awk
123456789012345
678901234567
890
$ echo '' | awk -v spaces=3 -v width=15 -f tst.awk
$
第一个测试用例表明您没有在全角输入行后打印空白行,第三个测试用例表明它不会删除空白行。通常我会使用 sprintf("%*s",spaces,"")
来创建 pad
字符串,但我在评论中看到它在您使用的显然非 POSIX awk 中不起作用。
这可能对你有用 (GNU sed):
sed 's/./&\n /80;P;D' file
这会将行拆分为长度为 80 并将以下行缩进 2 个空格。
或者如果您愿意:
s=' ' c=80
sed "s/./&\n$s/$c;P;D" file
要防止打印空行,请使用:
sed 's/./&\n/80;s/\n$//;s/\n /;P;D' file
或更容易:
sed 's/./\n &/81;P;D' file
假设我有一个标准的 80 列终端,执行带有长行输出的命令(即来自 ls
的标准输出)分成两行或更多行,并且想要缩进我所有 bash标准输出。
缩进应该是可配置的,1 或 2 或 3 或任何空格。
由此
lrwxrwxrwx 1 root root 24 Feb 19 1970 sdcard -> /storage/emula
ted/legacy/
至此
lrwxrwxrwx 1 root root 24 Feb 19 1970 sdcard -> /storage/emula
</code> <code>
ted/legacy/
阅读此 Indenting multi-line output in a shell script 所以我尝试使用管道 | sed 's/^/ /'
但给了我完全相反的结果,缩进了第一行而不是后续行。
理想情况下,我会在 profile.rc 或其他任何地方放置一个脚本,这样每次我打开交互式 shell 并执行任何命令时,长输出都会缩进。
一种可能的解决方案是使用纯 bash 字符串操作。
您可以使脚本读取 stdin
并格式化它读取的任何内容。
MAX_LEN=5 # length of the first/longest line
IND_LEN=2 # number of indentation spaces
short_len="$((MAX_LEN-IND_LEN))"
while read line; do
printf "${line:0:$MAX_LEN}\n"
for i in $(seq $MAX_LEN $short_len ${#line}); do
printf "%*s${line:$i:$short_len}\n" $IND_LEN
done
done
用法:(假设脚本保存为indent.sh
)
$ echo '0123456789' | ./indent.sh
01234
567
89
为此我会使用 awk。
awk -v width="$COLUMNS" -v spaces=4 '
BEGIN {
pad = sprintf("%*s", spaces, "") # generate `spaces` spaces
}
NF { # if current line is not empty
while (length > width) { # while length of current line is greater than `width`
print substr([=10=], 1, width) # print `width` chars from the beginning of it
[=10=] = pad substr([=10=], width + 1) # and leave `pad` + remaining chars
}
if ([=10=] != "") # if there are remaining chars
print # print them too
next
} 1' file
一行:
awk -v w="$COLUMNS" -v s=4 'BEGIN{p=sprintf("%*s",s,"")} NF{while(length>w){print substr([=11=],1,w);[=11=]=p substr([=11=],w+1)} if([=11=]!="") print;next} 1'
正如@Mark 在评论中建议的那样,您可以将其放入函数中并将其添加到 .bashrc
以便于使用。
function wrap() {
awk -v w="$COLUMNS" -v s=4 'BEGIN{p=sprintf("%*s",s,"")} NF{while(length>w){print substr([=12=],1,w);[=12=]=p substr([=12=],w+1)} if([=12=]!="") print;next} 1'
}
用法:
ls -l | wrap
Ed Morton 根据要求编辑:
与上面的 oguzismails 脚本非常相似,但应该与 Busybox 或任何其他 awk 一起使用:
$ cat tst.awk
BEGIN { pad = sprintf("%" spaces "s","") }
{
while ( length([=14=]) > width ) {
printf "%s", substr([=14=],1,width)
[=14=] = substr([=14=],width+1)
if ( [=14=] != "" ) {
print ""
[=14=] = pad [=14=]
}
}
print
}
$
$ echo '123456789012345678901234567890' | awk -v spaces=3 -v width=30 -f tst.awk
123456789012345678901234567890
$ echo '123456789012345678901234567890' | awk -v spaces=3 -v width=15 -f tst.awk
123456789012345
678901234567
890
$ echo '' | awk -v spaces=3 -v width=15 -f tst.awk
$
第一个测试用例表明您没有在全角输入行后打印空白行,第三个测试用例表明它不会删除空白行。通常我会使用 sprintf("%*s",spaces,"")
来创建 pad
字符串,但我在评论中看到它在您使用的显然非 POSIX awk 中不起作用。
这可能对你有用 (GNU sed):
sed 's/./&\n /80;P;D' file
这会将行拆分为长度为 80 并将以下行缩进 2 个空格。
或者如果您愿意:
s=' ' c=80
sed "s/./&\n$s/$c;P;D" file
要防止打印空行,请使用:
sed 's/./&\n/80;s/\n$//;s/\n /;P;D' file
或更容易:
sed 's/./\n &/81;P;D' file