是否可以结合 bash 变量搜索并替换为子字符串?

Is it possible to combine bash variable search and replace with substring?

我有这个功能:

#! /usr/bin/env bash

function underline() {
  U="${1//?/${2:--}}"
  echo -e "\n\n${U:0:${#1}}\n"
}

underline "" "^-v-"

将按预期工作:

$ ./u.sh "This is all you're going to see"

This is all you're going to see
^-v-^-v-^-v-^-v-^-v-^-v-^-v-^-v

它符合您的预期。最初它假定下划线字符就是 1 个字符。

为了“有趣”,我将其扩展为从单个字符下划线移动到重复字符串下划线(为什么?...好吧...因为我可以假设...在这个练习中实用价值几乎为零!).

所以,作为那种“让我们把事情变得如此困难以至于你需要写 2 页文档来解释正在发生的事情”的人,我想知道是否函数可以写成一行。我不是说:

function underline() { U="${1//?/${2:--}}"; echo -e "\n\n${U:0:${#1}}\n"; }

我认为您不能将 bash 的变量 search/replace 与所需的子字符串结合起来。

我知道这会在 zsh 中愉快地工作:

#! /usr/bin/env zsh

function underline() {
  echo -e "\n\n${${1//?/${2:--}}:0:${#1}}\n"
}

underline  "^-v-"

例如

$ ./u.sh "This is all you're going to see"

This is all you're going to see
^-v-^-v-^-v-^-v-^-v-^-v-^-v-^-v

但在 bash 中无法做到这一点(似乎)。

不,您不能将它们合并到 bash 中的单个参数扩展中。但是这个 printf(bash 中的内置函数)应该可以解决问题:

underline() { printf '%s\n%.*s\n' "" ${#1} "${1//?/${2:--}}"; }

underline "This is all you're going to see" "^-v-"

产出

This is all you're going to see
^-v-^-v-^-v-^-v-^-v-^-v-^-v-^-v