【问题标题】:Linux Rename command uppercase first letterLinux重命名命令首字母大写
【发布时间】:2012-12-23 21:10:32
【问题描述】:

我正在编写一个 Bash 脚本来清理我的音乐。

我希望它格式化所有文件名并制作它们,所以通过互联网搜索我写了这一行:

sed -i -e 's/[-_]/ /g' -e 's/ \+/ /g' -e **'s/\<[a-z]/\U&/g'** -e "s/$artist //g" -e "s/$album //g"

我曾经将文件名添加到文本文件然后 sed ,但后来我不知道如何将新名称应用于文件。

然后我开始尝试重命名并设法获得完全相同的结果 除了粗体部分,它应该使单词中的每个第一个字母大写。

rename 's/[-_]/ /g' * && rename 's/\s+/ /g' * && **rename 's/\s\w{1}/*A-Z*/g' *** && rename 's/^\d+[[:punct:]]\s//g' * && rename "s/$artist\s//g" * && rename "s/$album\s//g" * && rename "s/($ext)//g" *

现在,rename 中的代码正在运行(至少令人满意),仅在空格字符后找到一个字母,但问题在于替换。我尝试了许多不同的方法,结果都是焦点的第一个字母在这种情况下被交换为 A-Z。

在重命名手册页中,它说要将小写变为大写,您可以使用 's/a-z/A-Z/g',但很容易看出它仅在找到 a-z A-Z 时才适用。 所以这就是我需要帮助的地方。

如果有人知道如何像 sed 示例中那样执行此操作,那将是一个好处,其中 \

【问题讨论】:

  • 我注意到你在你的帖子上一直“签字”。 Don't do that.
  • 如果您已经有一个包含源名称和目标名称对的文本文件,那么您只需要sed 's/^/mv /' textfile | sh(尽管用空格等引用文件名会使事情变得复杂;这只是一个概念证明,而不是一个实际的答案)。

标签: regex linux bash sed rename


【解决方案1】:
rename -nv 's{ (\A|\s) (\w+) }{$1\u$2}xmsg'

这将查找字符串 \A 的开头或空格 \s 后跟至少一个或多个单词字符(a-z、0-9、下划线)\w+。它将所有单词序列的第一个字符大写。

【讨论】:

    【解决方案2】:

    这是一个 Perl 问题,因为 rename 是用 Perl 编写的,如何执行重命名的说明是 Perl 命令。

    s/// 中,为了让替换知道要插入哪个字母的大写版本,它必须从输入中“捕获”该字母。模式中的括号执行此操作,将捕获的字母存储在变量$1 中。而\u 在替换中使下一个字符变为大写。

    所以你可以这样做:

    $ rename 's/\s(\w)/ \u$1/g' *
    

    请注意,替换部分必须在大写字母之前插入一个空格,因为该模式包含一个空格,因此空格和原始字母都将被替换。您可以使用\b 来避免这种情况,这是一个仅在字边界处匹配的零宽度断言:

    $ rename 's/\b(\w)/\u$1/g' *
    

    你也不需要{1},因为\w(和正则表达式中的其他符号一样)默认匹配单个字符。

    最后,rename(1) 中的示例实际上是y/A-Z/a-z/,使用y/// 运算符,而不是s///y/// 是一个完全不同的运算符,它将所有出现的一组字母替换为另一组;这对你没有用处,它只是你想要大写的一些字符。

    【讨论】:

    • 感谢您的详尽解释。它极大地帮助了我实现我的目标。我重新编写了整个替换公式,最后得到了 rename 's/(\w)(\w{1,})/\u$1$2/g' *,它查找一个字母并在 $1 中捕获它,如果并且仅如果该字母后跟至少一个其他字母,则它将 $1 大写并使用 $2 打印出单词的其余部分。我在解决这个问题时遇到了一些问题,与 \b 边界并读到它不会匹配两个字母字符,但是 \B 做到了,尽管这也不起作用......我不确定为什么此时。
    • “1 或更多”是一个常见要求,因此有自己的符号 +。你可以写\w+而不是\w{1,}
    • \b 匹配从单词字符到非单词字符的转换(反之亦然)。 \B 正好相反,匹配其他任何地方。所以/\b\w\B/ 匹配一个单词字符,它前面不能有单词字符,但后面有一个单词字符。意思是 s/\b(\w)\B/\u$1/g 与您的公式具有相同的效果,但不会费心取出单词的第二个和后续字符只是为了将它们重新放入。
    • 啊,我明白了。我尝试做(\w)\B\w+,但最终将第一个字母大写,并删除了所有其他字母,但我现在明白\B 在它工作之后不需要任何东西。如果我理解正确,它会匹配所有匹配的内容?
    • 是的,没错。 \B 仅表示“字符串中的这一点必须在两个单词字符之间”(或在两个非单词字符之间,但在您的情况下,\w 之前的字符排除了这一点)。
    猜你喜欢
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多