首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用sed替换位于不同文件夹中的文件中的字符串

使用sed替换位于不同文件夹中的文件中的字符串
EN

Unix & Linux用户
提问于 2018-08-07 19:05:56
回答 3查看 3.8K关注 0票数 2

我有一个文件,它放在不同的文件夹中(文件扩展名为.mvw)。我想要编写一个脚本,这个脚本指向每个文件夹,并将一个字符串(在文件*.mvw中) "D3PLOT_1DForce“替换为文件夹的名称。

文件夹结构如下-

  • XYZ_DV_L02_P01
  • XYZ_DV_L02_P02
  • XYZ_DV_L02_P03

我写了以下剧本-

代码语言:javascript
复制
#!/bin/sh
for ii in XYZ_DV_L02* ; do
(cd "$ii")
find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/"${ii}"/g" "{}" \;
done

它可以用文件夹的名称替换字符串,但是它正在替换所有文件中第一个文件夹的名称。我认为sed不会进入循环的。

如何使sed在循环中工作,以便使用相应的文件夹名称来替换文件中的字符串?

EN

回答 3

Unix & Linux用户

发布于 2018-08-07 20:00:12

cd命令在子shell中执行,因此有效地不执行任何操作。因此,您的find命令将从父目录执行,对XYZ_DV_L02*中的每个子目录名称执行一次。sed的第一次调用会改变所有文件中的字符串,下面的sed调用不会找到字符串,但无论如何都会执行。

试试这个:

代码语言:javascript
复制
#!/bin/sh
for ii in XYZ_DV_L02* ; do
    find "$ii" -iname "*.mvw" -type f -exec sed -i "
      s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/${ii}/g" "{}" +
done

用于编辑Stéphane Chazelas的<#>Thanks

虽然我只是从只修复路径的问题中复制了find命令,但是有必要解释一下这些更改:

  • ${ii}没有引用,现在它是包含整个sed参数的引号的一部分。
  • 使用+而不是\;将导致find对多个文件执行一个sed命令,而不是对每个文件执行一个D16命令。

<#>编辑

对于来自注释的请求,这将用替换文本替换集合[-_a-zA-Z0-9]的每一个序列,然后是.h3d,这是包含.mvw扩展的文件名,这就是我理解注释的方式,但它似乎没有用。如果要访问模式中的文本,可以使用\1。您可能需要根据您的特殊需要对此进行调整。

代码语言:javascript
复制
#!/bin/sh
for ii in XYZ_DV_L02* ; do
    find "$ii" -iname "*.mvw" -type f -exec sed -i -r "
      s/([-_a-zA-Z0-9]+)\.h3d/${ii}.h3d/g" "{}" +
done
票数 4
EN

Unix & Linux用户

发布于 2018-08-07 19:22:29

尝尝这个,

代码语言:javascript
复制
#!/bin/sh
for ii in XYZ_DV_L02* ; do
cd "$ii"
find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce/"${ii}"/g" "{}" \;
cd ..
done

可以将目录更改为for循环中的第一个输入文件夹并找到该文件。但是在运行下一个循环之前,我们必须返回到父目录。

票数 1
EN

Unix & Linux用户

发布于 2018-08-08 06:14:33

如果您有一个只有几个子目录的目录结构,每个子目录都有要修改的.mvw文件,那么就不需要使用find了,因为您已经知道了文件的确切位置。

代码语言:javascript
复制
for pathname in XYZ_DV_L02*/*.mvw; do
    sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname"
done

这将遍历指定子目录中的所有.mvw文件,并将字符串替换为目录名。参数展开${pathname%%/*}$pathname字符串中的第一个/之后删除所有内容。

测试:

代码语言:javascript
复制
$ tree
.
|-- XYZ_DV_L02_P01
|   `-- somefile.mvw
|-- XYZ_DV_L02_P02
|   `-- somefile.mvw
`-- XYZ_DV_L02_P03
    `-- somefile.mvw

3 directories, 3 files

$ cat XYZ_DV_L02_P0*/*.mvw
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!

(在这里运行循环)

代码语言:javascript
复制
$ cat XYZ_DV_L02_P0*/*.mvw
Hello XYZ_DV_L02_P01_EffPlStrainMax_VonMisesMax!
Hello XYZ_DV_L02_P02_EffPlStrainMax_VonMisesMax!
Hello XYZ_DV_L02_P03_EffPlStrainMax_VonMisesMax!

显然,如果您有一个很深的层次结构,那么无论如何您可能需要使用find,但是您可以在find内部而不是在find之外执行循环:

代码语言:javascript
复制
find XYZ_DV_L02*/ -type f -name '*.mvw' -exec sh -c '
    for pathname do
        sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname"
    done' sh {} +

在这里,我们发现所有.mvw文件下的任何一个目录与模式XYZ_DV_L02*/匹配。对于这些找到的文件,我们运行一个循环,在这个答案的开头执行与循环相同的操作。这将用相应的D3PLOT_1DForce目录名替换任何目录下的所有.mvw文件中的字符串XYZ_DV_L02*

相关信息:

这个答案假设GNU、sed或其他sed实现在没有选项参数的情况下使用-i进行就地编辑。

票数 1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/461144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档