“重命名”正则表达式中的反向引用

“重命名”正则表达式中的反向引用

我的目录中有很多名为“bar_foo.txt”的文件,我想将它们重命名为“foo_bar.txt”。

在 中sedvim其正则表达式类似于's/\(bar\)_\(foo\)/\2_\1/g',在替换中反向引用搜索。

  1. 有没有办法做到这一点rename?我见过一些黑客通过管道传输lssedto bash,但这显然不是一个令人惊奇的方法。

  2. 还有其他工具可以做到这一点吗?

  3. 正则表达式的“sed 和 vim 风格”有名称吗?

答案1

如果您rename使用 Perl 正则表达式实现(如在 Debian/Ubuntu/... 或prenameArch Linux 上),则需要$1而不是\1.另外,捕获括号时没有反斜杠:

rename 's/(.*)_(.*)/$2_$1/' *_*

如果没有,您必须自己实施。

#! /bin/bash
for file in *_* ; do
    left=${file%_*}
    right=${file##*_}
    mv "$file" "$right"_"$left"
done

注意:正如所写,两个命令都重命名a_b_cc_a_b.要获取b_c_a,请将第一个捕获组更改为.*?(在第一种情况下),或在第二种情况下将第一个捕获组更改%%%##to 。#

答案2

执行此操作的标准工具是pax- 尽管它使用硬链接和副本比直接移动效果更好。当然,所有的举动本质上都是创建一个新链接并删除一个旧链接。

我更喜欢脱离这些步骤——暂时我有同一棵树的两个副本,可以进行比较和对比。这在动态重命名文件时尤其重要 - 对文件名进行编辑操作的结果可能与现有链接名相同,在这种情况下哪个文件获取该名称?

因此,要按照 POSIXly 的要求做这件事,你可以这样做:

pax -rwls'|^\(bar\)_\(foo\).txt$|\2_\1.txt|' -s'|.*||' *_*.txt .

当您完成后,结果将是指向相关文件的单独链接。验证结果是否符合您的要求并删除旧的。

并且sed,vim正则表达式样式是标准的布雷

答案3

  1. 随着实用程序Linuxrename,不,这个只做基本的字符串替换。对于基于 Perl 的rename,是的,请参阅乔罗巴的回答

  2. 使用 zsh 的zmv:

    autoload -U zmv      # put this in your ~/.zshrc
    zmv '(*)_(*).(*)' '${2}_$1.$3'
    zmv -w '*_*.*' '${2}_$1.$3'
    

    上面的两个zmv调用是等效的。要在子目录中执行操作,您可以使用zmv -w '**/*_*.*' '$1/${3}_$2.$4'

  3. Vi(m)和sed的使用(扩展)基本正则表达式。也可以看看为什么我的正则表达式在 X 中有效但在 Y 中无效?

相关内容