在 shell 脚本中缩进多行输出

我正在尝试更改 Ubuntu Amazon EC2框中的每日消息(MOTD) ,以便在 SSH 时显示我的一个目录的 git 状态。

所有默认 MOTD 文件的输出在每一行的开头都有两个空格,所以它看起来很好地缩进了,但是因为我的 git status输出跨越了几行,所以如果我在 echo -n " "之前只缩进了第一行。

有什么办法能让它缩进每一行吗?

34195 次浏览

Pipe it to sed to insert 2 spaces at the beginning of each line.

git status | sed 's/^/  /'

Building on @Barmar's answer, this is a tidier way to do it:

indent() { sed 's/^/  /'; }


git status | indent
other_command | indent

Thanks to @Barmar and @Marplesoft for some nice simple solutions - here is another variation that others might like - a function you can tell how many indent levels using pr:

indent() {
local indentSize=2
local indent=1
if [ -n "$1" ]; then indent=$1; fi
pr -to $(($indent * $indentSize))
}


# Example usage
ls -al | indent
git status | indent 2

Here's a function I wrote to also indent stderr:

function indented {
local PIPE_DIRECTORY=$(mktemp -d)
trap "rm -rf '$PIPE_DIRECTORY'" EXIT


mkfifo "$PIPE_DIRECTORY/stdout"
mkfifo "$PIPE_DIRECTORY/stderr"


"$@" >"$PIPE_DIRECTORY/stdout" 2>"$PIPE_DIRECTORY/stderr" &
local CHILD_PID=$!


sed 's/^/  /' "$PIPE_DIRECTORY/stdout" &
sed 's/^/  /' "$PIPE_DIRECTORY/stderr" >&2 &
wait "$CHILD_PID"
rm -rf "$PIPE_DIRECTORY"
}

Use it like:

indented git status
indented ls -al

For efficiency, you can do it without calling any tools like sed:

output=$(git status); echo "  ${output//$'\n'/$'\n'  }."

Or, in a function:

indent()
{
local unindented
unindented="$(< /dev/stdin)"
echo "  ${unindented//$'\n'/$'\n'  }."
}


git status | indent

How it works: Bash parameter expansion replaces every "end of line" to "end of line" + . The first line is not preceded by "end of line", so we prepend to the whole string.

This saves the time to start the whole sed/etc process (though, in this case, where the output is not yet in a variable, it might cost more time to allocate the variable, if the text is bigger than your sed binary).

Like most solutions, tabs in the original output, which may look like 8 spaces, are simply prepended with 2 spaces, and the tabs shrinks, and thus it still looks like idented with 8 spaces. This might be desired or not.