我想将任何特殊字符(不是数字或字母)替换为一个'-'。
我在下面的代码中尝试了一些字符,但是当重复字符超过1次时,它将不起作用,因为仍然会有多个'-'。
#!/bin/bash
for f in *; do mv "$f" "${f// /-}"; done
for f in *; do mv "$f" "${f//_/-}"; done
for f in *; do mv "$f" "${f//-/-}"; done
我想要什么:
test---file -> test-file
test file -> test-file
test______file -> test-file
teeesst--ffile -> teeesst-ffile
test555----file__ -> test555-file
请解释您的答案,因为我对bash,regexp不太了解...
答案 0 :(得分:1)
您可以使用tr
(如注释中上面所示),或者实际上,sed
在这种情况下更有意义。例如,给定您的文件名列表:
$ cat fnames
test---file
test file
test______file
teeesst--ffile
test555----file__
您可以使用sed
表达式:
sed -e 's/[[:punct:] ][[:punct:] ]*/-/' -e 's/[[:punct:] ]*$//'
使用/输出示例
$ sed -e 's/[[:punct:] ][[:punct:] ]*/-/' -e 's/[[:punct:] ]*$//' fnames
test-file
test-file
test-file
teeesst-ffile
test555-file
根据文件名的存储方式,可以单独使用命令替换,也可以使用进程替换并将更新后的名称输入{{1} }循环或类似的内容。
答案 1 :(得分:1)
在Linux的各种发行版中,有几个不同的rename
(或prename
)命令可用于处理正则表达式替换。
但是您也可以使用Bash的扩展globing来完成其中的一些操作。模式${var//+([-_ ])/-}
表示用一个连字符替换方括号中列出的任何一个或多个字符。
shopt -s extglob
# demonstration:
for file in test---file 'test file' test______file teeesst--ffile test555----file__
do
echo "${file//+([-_ ])/-}"
done
输出:
test-file
test-file
test-file
teeesst-ffile
test555-file-
扩展的+()
类似于正则表达式中的.+
。其他Bash扩展的问题(来自man bash
):
?(pattern-list)
Matches zero or one occurrence of the given patterns
*(pattern-list)
Matches zero or more occurrences of the given patterns
+(pattern-list)
Matches one or more occurrences of the given patterns
@(pattern-list)
Matches one of the given patterns
!(pattern-list)
Matches anything except one of the given patterns
请注意,最后的连字符未在此处删除,但可能使用了附加的参数扩展:
file=${file/%-/}
表示删除字符串末尾的连字符。