sed:无法使用变量替换最新出现的文本,包括“-”破折号

sed: Can't replace latest text occurrence including "-" dashes using variables

尝试使用 sed 将一个文本替换为另一个文本,使用一个变量。在变量的内容包含破折号“-”并且 sed 尝试解释它之前,它一直有效。

需要注意的是,在此上下文中,我只需要替换原始变量 ${src} 的最新出现,这就是为什么我的 sed 命令如下所示:

sed -e "s:${source}([^${source}]*)$:${dest}:"

“sed”对我来说有点陌生,我总是尽可能用“replace”或“awk”得到我的结果,但在这里我试图使代码尽可能通用,因此使用 sed。如果您想到其他解决方案,那也是可行的。

问题示例:

# mkdir "/home/youruser/TEST-master"
# source="TEST-master" ; dest="test-master" ; find /home/youruser/ -depth -type d -name '*[[:upper:]]*' | grep "TEST" | sed -e "s:${source}([^${source}]*)$:${dest}:"
sed: -e expression #1, char 46: Invalid range end

鉴于我不知道每个变量可能包含多少个破折号,是否有任何 sed 专家知道我怎样才能完成这项工作?

确切上下文:我正在为其重写一个函数以递归小写文件和目录的开源项目 LinuxGSM。 Bash 我正在处理的功能并在此处发表评论:https://github.com/GameServerManagers/LinuxGSM/issues/1868#issuecomment-996287057

如果我对上下文的理解正确,实际目标是采用在其最后一个元素中包含一些大写字符的路径,并创建一个最后一个元素小写的版本。例如,/SoMe/PaTh/FiLeNaMe 将转换为 /SoMe/PaTh/filename。如果是这种情况,不要使用字符串替换,而是使用 dirnamebasename 将其拆分为组件,大写最后一个,然后重新组合:

parentdir=$(dirname "$src")
filename=$(basename "$src")
lowername=$(echo "${latestpath}" | tr '[:upper:]' '[:lower:]')
dst="$parentdir/$lowername"

(旁注:将参数引用到 tr 很重要,以确保 shell 不会将它们视为文件名通配符并将它们替换为匹配文件列表。)

只要路径包含至少一个“/”但不以“/”结尾,您就可以使用 bash 替换而不是 dirnamebasename:

parentdir="${src%/*}"
filename="${src##*/}"

只要您使用的是 bash v4.0 或更高版本,您还可以使用内置替换来进行小写:

lowername="${filename,,}"