【问题标题】:Replace multiple underscores in filename using bash script使用 bash 脚本替换文件名中的多个下划线
【发布时间】:2022-01-07 13:42:06
【问题描述】:

阅读herehere 我发现了这个解决方案,用bash 替换文件名中的两个下划线:

for file in *; do
  f=${file//__/_}
  echo $f
done;

但是,我如何最轻松地扩展此表达式以仅用一个替换任意数量的下划线?

【问题讨论】:

  • 如果您扩展了通配(如果尚未启用,请使用shopt -s extglob 启用它),您可以使用f="${f//+(_)/_}"。例如。对于文件“test_____something__else.txt”,for f in test_*; do f="${f//+(_)/_}"; echo $f; done 返回test_something_else.txt。更多细节在这里:askubuntu.com/a/889746

标签: bash macos replace


【解决方案1】:

您可以使用sed 使用简单的正则表达式

for file in *; do
  f=$(echo "$file" | sed -e 's/_\+/_/')
  echo "$f"
done;

此正则表达式匹配一个或多个下划线 (_\+) 并仅用一个 (_) 替换它们

【讨论】:

  • echo "$file",不是echo $file;和echo "$f",而不是echo $f。见I just assigned a variable, but echo $variable shows something else!
  • (另外,这将比在循环中使用 OP 的原始代码慢很多;为每个文件启动管道很昂贵!)
  • 编辑了我的答案以更正变量的使用,你完全正确地认为它变慢了。我不会在任何有很多文件的目录中使用它
【解决方案2】:

通常,将原始代码放入循环中会比执行其他任何操作更快。

for file in *; do
  f=$file
  while [[ $f = *__* ]]; do
    f=${f//__/_}
  done
  echo "$f"
done

更好的是,如果您使用的是现代 shell 版本,则可以启用扩展 glob,它提供类似正则表达式的功能:

shopt -s extglob
for file in *; do
  f=${file//+(_)/_}
  echo "$f"
done

【讨论】:

  • 太好了,2 号真的让事情变得更容易了。作为一个零星的 bash 用户,我发现仅仅通过搜索手册和描述很难弄清楚这些事情。
【解决方案3】:

GNU tr--squeeze-repeats:

$ echo foo_______bar | tr --squeeze-repeats _
foo_bar

如果您使用的是 BSD tr,则可以改用 -s

$ echo foo_______bar | tr -s _
foo_bar

【讨论】:

    【解决方案4】:

    这个Shellcheck-clean 纯shell 代码应该适用于任何符合POSIX 的shell,包括bashdash

    for file in *; do
        while :; do
            case $file in
                *__*)   file=${file%%__*}_${file#*__};;
                *)      break;;
            esac
        done
        printf '%s\n' "$file"
    done
    
    • ${file%%__*} 扩展为 $file,其中第一个 __ 和之后的所有字符都被删除(例如,a__b__c 产生 a)。
    • ${file#*__} 扩展为 $file,删除了直到并包括第一个 __ 在内的所有字符(例如,a__b__c 生成 b__c)。
    • 请参阅Why is printf better than echo? 的已接受且优秀的回答,了解为什么使用printf '%s\n' "$file" 而不是echo "$file"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      • 2011-02-12
      • 1970-01-01
      • 2013-11-08
      • 2013-01-01
      • 2014-11-27
      • 2014-11-30
      相关资源
      最近更新 更多