缩进长行标准输出

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 -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