Shell 函数将其第一个参数居中

Shell 函数将其第一个参数居中

在纳米文本编辑器中,我可以将选择传输到命令中,并且我经常需要将文本居中,所以我想出了以下代码

center() {
  str=$1
  # Strip leading and trailing whitespace from the string
  str=$(echo "$str" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
  str_len=${#str}
  margin=$(((80 - str_len) / 2))
  printf "%*s%s%*s\n" $margin "" "$str" $margin ""
}

但我对脚本了解不多,所以我想知道如何改进这段代码。

为什么要链接到 bash 解决方案?我不使用这个 shell,我只是想让它与 sh 一起运行

答案1

假设您正在使用bashshell(如果不使用,请参阅此答案的末尾),您可以使用标准变量扩展和扩展通配模式(匹配一个或多个类似空格的字符)更有效地bash从字符串中去除侧翼空格:str+([[:space:]])

shopt -s extglob

str=$1
str=${str##+([[:space:]])}  # strip at start
str=${str%%+([[:space:]])}  # strip at end

我们想要打印右对齐到 ( 给出的列w+s)/2,其中w是终端的宽度(由 输出tput cols,但您也可以使用$COLUMNS)并且s是字符串 ( ${#str}) 的长度:

printf '%*s\n' "$(( ( $(tput cols) + ${#str} ) / 2 ))" "$str"

功能:

center () (
    shopt -s extglob

    str=$1
    str=${str##+([[:space:]])}
    str=${str%%+([[:space:]])}

    printf '%*s\n' "$(( ( $(tput cols) + ${#str} ) / 2 ))" "$str"
)

请注意,函数的主体是一个子 shell。这样extglobshell 选项的设置就不会溢出到调用 shell 中。

不依赖extglob(适用于任何sh):

center () {
    str=$(printf '%s\n' "$1" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
    printf '%*s\n' "$(( ( $(tput cols) + ${#str} ) / 2 ))" "$str"
}

如果要将其格式设置为静态 80 列宽度,请替换$(tput cols)为。80

答案2

如果中间没有连接多个空格,则可以使用以下命令简化修剪str=$(echo $1)

center () {
  str=$(echo $1)
  len=${#str}
  margin=$((($COLUMNS - len) / 2))
  printf "%${margin}s%s\n" " " "$str"
}

您不需要在 后面添加空格$str

相关内容