有没有什么方法可以同时替换多个模式的变量中的文本,甚至使用反向引用?
例如,我有FILE=filename.ext
并且我想将其更改为filename_sometext.ext
.但我不知道文件扩展名是.ext
.我所知道的是扩展名在最后一个点之后。所以我可以分两步完成:
EXT=${FILE##*.}
FILE=${FILE%.*}_sometext.$EXT
我可以一步完成(例如${FILE/.\(*\)/_sometext.\1}
[这不起作用])吗?
顺便说一句,我需要在没有sed
/ awk
/etc 的纯 shell 中执行此操作。我的外壳是ksh
,但如果有办法用 bashisms 做到这一点,我也想知道。
答案1
答案2
在这种特殊情况下,我认为FILE=${FILE%.*}_sometext.${FILE##*.}
可以完成这项工作。
答案3
变量。
在任何 shell 中,您都可以连接变量或值:
$ a=One; b=Two; c=Three
$ d="$a$b$c"; echo $d
OneTwoThree
这${parameter%word}
结构是 POSIX长期以来,大多数 shell 都支持该功能。
假设FILE=filename.ext
,你可以这样做:
$ FILE="${FILE%.*}_sometext.${FILE##*.}"; echo "$FILE"
filename_sometext.ext
这是一行(根据要求)并且适用于大多数 shell。
也可以使用变量(即使有几个点):
#!/bin/bash
FILE=file.one.name.ext
ADDTEXT="_sometext"
EXT="${FILE##*.}"
echo "EXT=$EXT"
echo "final FILE=${FILE%.*}${ADDTEXT}.$EXT"
或者,只用一行:
ONEFILE=${FILE%.*}${ADDTEXT}.${FILE##*.}
echo "one FILE=$ONEFILE"
模式替换
棘手的是尝试使用${parameter/pattern/string}
“模式替换”。
变量可以在许多 shell 中工作(甚至 busybox ash):
NEWTEXT="${ADDTEXT}.${FILE##*.}"
echo "ash FILE=${FILE/.*/${NEWTEXT}}"
但在较老的sh
埃尔斯则不然。
仅适用于FILE=filename.ext
:
这适用于 bash(以及 ksh、ksh93、mksh、zsh),但不适用于 ash、dash、sh 或 csh
echo "bash FILE=${FILE/%.*/${ADDTEXT}.${FILE##*.}}"
请注意,它使用 字符%
来指示参数末尾的匹配(但是,遗憾的是它是贪婪的并且吃掉了 中的所有点FILE=file.one.name.ext
)。
结论
控制替换贪婪程度的最佳方法是使用单独的变量(而不是“模式替换”中的一些变量。)
答案4
FILE="${FILE%.*}_sometext${FILE#"${FILE%.*}"}"
如果 shell 变量$FILE
包含 a ,.
上面的命令将重新分配给它旧值减去最后一个之后的所有.
内容_sometext
并保留旧值的最后一个.
以及之后的所有内容。
所以:
FILE=some.dot
FILE="${FILE%.*}_sometext${FILE#"${FILE%.*}"}"
printf %s\\n "$FILE"
some_sometext.dot
如果 shell 变量$FILE
是不是包含一个点,那么_sometext
字符串仅附加到旧值的末尾:
FILE=no_dots_at_all
FILE="${FILE%.*}_sometext${FILE#"${FILE%.*}"}"
printf %s\\n "$FILE"
no_dots_at_all_sometext
如果您没有像我最后那样嵌套参数扩展,那么这与您可能得到的行为有重要不同:
FILE=no_dots_at_all
FILE="${FILE%.*}_sometext${FILE##*.}"
printf %s\\n "$FILE"
no_dots_at_all_sometextno_dots_at_all
当您嵌套参数扩展时,它会从内到外进行求值,因此首先发生的事情是:
for FILE in some.dot no_dots_at_all
do printf %s\\n '${FILE#'"${FILE%.*}"'}'
done
${FILE#some}
${FILE#no_dots_at_all}
...外壳删除所有匹配的位并使用剩余部分作为从外部扩展中剥离的模式。所以当有不是任何匹配的位和变量都会完全扩展,外部扩展会被剥离全部变量的值,而不是将其替换到表达式中两次。