首页 > 解决方案 > 如何在 Bash 中替换 N 个重复的特殊字符?

问题描述

我想将任何特殊字符(不是数字或字母)替换为一个“-”。

我用一些字符尝试了下面的代码,但是当字符重复超过 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 不太了解......

标签: linuxstringbashreplaceopensuse

解决方案


在各种 Linux 发行版中有几个不同的rename(或prename)命令可以处理正则表达式替换。

但是你也可以使用 Bash 的扩展通配符来做一些事情。该模式${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-

扩展的 glob+()类似于.+正则表达式。其他 Bash 扩展 glob(来自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/%-/}

它说要删除字符串末尾的连字符。


推荐阅读