我有一组具有以下文件名结构的文件:
aa_bbbbb_cccccccc_dddddd.txt
我想用从文件内容中提取的cccccccc
变量值替换第三个元素。value
文件名的4个组成部分的值发生变化,因此我无法使用字符串替换来替换,但我需要根据要替换的子字符串的位置进行替换。
有什么建议如何仅使用 bash 脚本来解决这个问题吗?
我无法使用重命名。它似乎在 cygwin 中不起作用,并且无论如何,我无法使用字符串替换。如果我们将“_”视为分隔符,我需要将第三个字段替换为变量中包含的值。
答案1
bash
确实有一个分割运算符,与 ksh 或 POSIX 中的一样尴尬sh
:当您将参数扩展不加引号时执行(并且通常是不需要的)IFS 分割。
cmd $var
做$var
对字符进行分割$IFS
(并且还执行通配符),也称为臭名昭著的 split+glob 运算符。
一般来说,您不想要这就是您通常需要 的原因cmd "$var"
,甚至cmd -- "$var"
对于那些接受选项的命令也是如此。
但是在这里,您可以使用它来进行拆分_
。
和:
IFS=_
set -o noglob
parts=( $file'' )
$file
被分割_
并将结果部分存储在$parts
数组中。
然后你可以这样做:
parts[2]=$value
更改第三部分(在 bash 中,与 ksh 类似,但与大多数其他 shell 不同,数组元素索引从 0 开始,因此第三个元素位于 中${parts[2]}
)。
您可以使用_
s 将它们加入到 pack 中:
newfile="${parts[*]}"
答案2
value
带有变量的文件示例
value=xxx
然后,使用珀尔的rename
:
file=aa_bbbbb_cccccccc_dddddd.txt
rename -n 's/^(.+?_.+?)_.+?_(.*)/${1}_foo_$2/' ./"$file"
当输出看起来令人满意时删除-n
(又名)。dry-run
答案3
使用Bash 参数扩展:
${parameter##word}
word
从中删除最长的匹配前缀模式parameter
${parameter%word}
word
删除最短的匹配后缀模式parameter
file="aa_bbbbb_cccccccc_dddddd.txt"
value="replace me"
suffix=${file##*_} # dddddd.txt
prefix=${file%_*} # aa_bbbbb_cccccccc
prefix=${prefix%_*} # aa_bbbbb
mv "$file" "${prefix}_${value}_${suffix}"
或者短一点
file="aa_bbbbb_cccccccc_dddddd.txt"
value="replace me"
prefix=${file%_*}
mv "$file" "${prefix%_*}_${value}_${file##*_}"