【问题标题】:Convert last hyphen in filename using BASH使用 BASH 转换文件名中的最后一个连字符
【发布时间】:2015-06-16 05:22:53
【问题描述】:

我的任务是一个主要的文件重命名项目。我将重命名的其中一些文件包含多个连字符。我需要将名称中的最后一个连字符替换为下划线,以便将文件重命名为我们的新命名约定。

谁能向我解释为什么在下面的测试代码中最后一个连字符没有被下划线替换?

#!/bin/bash

image_name="i-need-the-last-hyphen-removed.psd"

echo -e "Normal: ${image_name}"
echo "Changed: ${image_name/%-/_}"

我正在寻找的输出应该模仿以下内容:

Normal: i-need-the-last-hyphen-removed.psd
Changed: i-need-the-last-hyphen_removed.psd

脚本逻辑是通过在此处找到的以下文档创建的:http://tldp.org/LDP/abs/html/string-manipulation.html

我尝试过逃避炒作,但没有成功。我已经放弃了,与我过去使用的 SED 和/或 BASH_REMATCH 解决方案相比,这将被证明是最优雅的解决方案。

任何帮助都会很棒。先感谢您。

【问题讨论】:

  • echo "${image_name%-*}_${image_name##*-}"
  • 看看rename命令。
  • @AlexP.:+1 非常好。
  • @AlexP。即使是简短的答案也应该作为答案发布,而不是 cmets。

标签: regex linux bash shell sed


【解决方案1】:

我建议对此类任务使用重命名工具。它与 sed 模式相似。

rename 's/(.*)-/$1_/' *.psd  

由于 .* 是贪婪的,这样最后一个 '-' 将被捕获,其中 (.*) 被分组捕获。右边部分不会改变。

使用 *.psd 您将捕获当前文件夹中的所有 psd 文件

【讨论】:

  • 这是我在提出您的建议后收到的。然后我将 \1_ 换成 $1_ 并且没有运气。 Machine-Name$ rename 's/\(.*\)-/\1_/' *.psd \1 better written as $1 at (eval 4) line 1.
  • 是的,用 1 美元代替 \1,我已经测试并在这里工作.. 用 1 美元
  • 在分组不需要转义()时,我已经编辑了答案。现在应该没问题了
【解决方案2】:

非常感谢@alex-p 的以下建议。正如我最初所说,我不想使用 SED 或 BASH_REMATCH 或任何其他复杂的 REGEX。这完美无缺。

echo "${image_name%-}_${image_name##-}"

【讨论】:

    【解决方案3】:

    您可以使用sed 作为:

    sed -r "s/(.*)-(.*)/\1_\2/"
    

    这将有两个捕获的组(1.在最后一个- 2.在最后一个-之后)将与_连接 或者

    sed -r "s/-([^-]*$)/_\1/"
    

    这将有一个捕获的组,它将- 替换为_,然后捕获的组将最后连接起来。

    【讨论】:

      【解决方案4】:

      ${image_name/%-/_}"只有-$image_name 的终止符/后缀时才起作用(例如在 mystring- 中)。

      尝试使用 sed:

      $> echo i-need-the-last-hyphen-removed.psd | sed -r 's/-([^-]*$)/_\1/'
      i-need-the-last-hyphen_removed.psd
      

      【讨论】:

      • 出于教育目的,您能向我解释一下后端是什么意思吗?
      • @Jesse Riddle:答案已更新,不再那么晦涩难懂。 back end 取自您的来源 linkIf $substring matches back end of $string, substitute $replacement for $substring
      • 我是这么理解的。我正在寻找“-”的 $substring 并使用“%”从后面看(基本上是向右看 -> 向左看)。然后我的替换是“_”。所以我想我不明白为什么它没有使用我的逻辑找到最后一个连字符。 (显然这是错误的,但我试图了解原因。)
      • @Jesse Riddle:在我的理解中,${string/%substring/replacement} bash 构造仅适用于 exact substring 模式,而不是尝试匹配包含最短/最长模式的任何内容substring 从右到左。因为image_name 在连字符旁边有很多字符,所以这种方法不起作用。这就是我的解释。
      猜你喜欢
      • 2019-10-13
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      • 2016-08-06
      • 2012-04-26
      • 1970-01-01
      • 1970-01-01
      • 2019-03-28
      相关资源
      最近更新 更多