在文件中查找和替换

时间:2011-03-18 08:52:42

标签: regex perl replace sed awk

我需要搜索类似的模式:

timeouts = {default = 3.0; };

并将其替换为

timeouts = {default = 3000.0;.... }; 

即将超时乘以系数1000。

有没有办法对目录中的所有文件执行此操作

EDIT :

请注意,某些文件是目录中的符号链接。是否有办法为符号链接完成此操作?

请注意,超时也存在于文件中作为子字符串,因此我想确保只更换此行。使用sed awk perl可以接受任何解决方案。

4 个答案:

答案 0 :(得分:1)

尝试一下:

for f in *
do
    sed -i 's/\(timeouts = {default = [0-9]\+\)\(\.[0-9]\+;\)\( };\)/\1000\2....\3/' "$f" 
done

它将为当前目录中的每个文件进行替换。某些版本的sed需要-i选项后的备份扩展名。你可以提供这样的:

sed -i .bak ...

某些版本不支持就地编辑。你可以这样做:

sed '...' "$f" > tmpfile && mv tmpfile "$f"

请注意,这显然实际上并未乘以1000,因此如果数字为3.1,则会变为“3000.1”而不是3100.0

答案 1 :(得分:0)

$ perl -pi.bak -e 's/\w+\s*=\s*{\s*\w+\s*=\s*\K(-?[0-9.]+)/sprintf "%0.1f", 1000 * $1/eg' *

注意:

  • 正则表达式只匹配数字(参见perlre中的\K
  • /e表示评估替换
  • 我在替换中包含sprintf,以防您需要更好地控制格式
  • Perl的-i可以对一堆文件进行操作

修改

有人指出,有些文件是shambolic链接。鉴于此过程不是幂等的(在同一个文件上运行两次很糟糕),最好生成一个唯一的文件列表,以防其中一个链接指向列表中其他位置的文件。以下是find的示例,但预先存在的列表的代码应该是显而易见的。

$ find -L . -type f -exec realpath {} \; | sort -u | xargs -d '\n' perl ...

(假设你的文件名都没有包含换行符!)

答案 2 :(得分:0)

你可以这样做

perl -pi -e 's/(timeouts\s*=\s*\{default\s*=\s*)([0-9.-]+)/print $1; $2*1000/e' *

答案 3 :(得分:0)

对于您决定使用上述任何解决方案的一个建议 - 考虑如何重构以避免必须再次修改所有这些文件以进行此类更改,这可能是值得的。

  • 所有这些脚本都具有类似的功能吗?
  • 你能创建一个他们都会用于共享子程序的模块吗?
  • 在模块中,您是否可以使用一行来获得乘数?

对我来说,任何时候我需要在多个文件中进行类似的更改,这是lazy以后节省时间和维护问题的最佳时机。