从目录中的一组文件中删除一组相同的行

从目录中的一组文件中删除一组相同的行

我有一个 drupal 网站,它将其配置导出到 yaml 文件中。对于其 Web 表单组件,我们有大约 200 个 Web 表单,可将​​提交的内容抄送至内部电子邮件地址,以跟踪

我们希望从所有 Web 表单中删除该电子邮件,最简单的方法是将其从 yaml 配置文件中删除,然后重新导入它们。

因此,我当前的工作流程是打开其中一个文件,找到包含 的行email_webdev:,然后删除它和接下来的 42 行,保存文件,打开下一个,清洗 ,重复,大约 200 个文件。

我正在寻找一个单行或脚本,它将自动从它们出现的所有文件中删除一组有序的相同 42 行。

技术说明

在我们的配置目录中,有大约 200 个文件,我想从中删除一组相同的行:

$ ls webform.webform.*
webform.webform.incoming_student_housing_applica.yml
webform.webform.info_for_students.yml
webform.webform.info_request_for_viewbook.yml
webform.webform.inquire_about_a_project.yml

每个 Webform 配置 yaml 都是几百行配置数据,缩进,具有基本格式。这是一个示例摘录,带有前导行号:

....
170   test:
171     roles: {  }
172     users: {  }
173     permissions: {  }
174   configuration:
175     roles: {  }
176     users: {  }
177     permissions: {  }
178 handlers:
179   email_webdev:
180     id: email
181     label: 'Webdev Email'
182     handler_id: webdev_email
183     status: true
184     conditions: {  }
185     weight: 0
186     settings:
... 
214       parameters: {  }
215 variants: {  }
216 uuid: 6073470f-bb3b-40ad-8440-a7cb5f3be4d2

上面摘录中第 179-214 行的 42 行节是我想要从该目录中的 200 多个文件中删除的内容。所以我手动做的是删除 vim 中的第 179-214 行,然后保存。结果如下:

...
170   test:
171     roles: {  }
172     users: {  }
173     permissions: {  }
174   configuration:
175     roles: {  }
176     users: {  }
177     permissions: {  }
178 handlers:
179 variants: {  }
180 uuid: 6073470f-bb3b-40ad-8440-a7cb5f3be4d2

它有 42 行长。这 42 行在文件之间是相同的,并且顺序完全相同,但节在文件中的不同位置开始。例如,在一个文件中,它可能从第 1068 行开始,在另一个文件中,从第 872 行开始。

$ grep -n email_webdev *
webform.webform.404.yml:183:  email_webdev:
webform.webform.accommodations_letter_request_fo.yml:219:  email_webdev:
webform.webform.agency_survey.yml:219:  email_webdev:
...

我所能弄清楚的就是使用 grep 开关-A来查找模式匹配后的行:

$ grep -A42  email_webdev *
webform.webform.volunteer_sign_up.yml:  email_webdev:
webform.webform.volunteer_sign_up.yml-    id: email
webform.webform.volunteer_sign_up.yml-    label: 'Webdev Email'
webform.webform.volunteer_sign_up.yml-    handler_id: webdev_email
webform.webform.volunteer_sign_up.yml-    status: true
webform.webform.volunteer_sign_up.yml-    conditions: {  }
webform.webform.volunteer_sign_up.yml-    weight: 0
webform.webform.volunteer_sign_up.yml-    settings:
...

所以,这些是我想从该文件(以及目录中的所有文件)中删除的行,,我不能只是让它删除该行id: email,因为它出现在其他电子邮件响应中,我也不能只是模式匹配任何其他行,例如weight: 0,它也出现在几乎所有其他元素中,并且conditions: { }。他们只能读取此节中的行,该节以 开头email_webdev:,并继续到接下来的 42 行,在每个文件中都是相同的。

有没有更简单的方法来做到这一点?

答案1

请先尝试此操作,然后mv检查.out创建的新文件是否完全符合您的要求。重新启用mv覆盖原始文件的操作。

for file in webform.webform.*; do
    awk '/^  email_webdev:$/{n=42}{if(!n){print}else{n--}}' "$file" > "$file.out"
    mv -- "$file.out" "$file"
done

awk 脚本检测一行确切地像这样:

  email_webdev:

即,两个空格email_webdev:,行尾字符。

一旦检测到该行,它就会设置n=42,从而停止打印该行,然后仅在计数到 42 行后才重新开始打印。

答案2

您可以使用ex行编辑器来执行此操作。

for f in webform.webform.*; do
  printf '%s\n' /email_webdev:/ .,+41d x | ex -s "$f"
end

在职的:

  • 每当我们看到相对寻址时,我们应该使用ed/ex行编辑器,除非文件大小很大,因为它们支持多种行寻址模式。
  • printf正在发出ex编辑器代码,该代码 ex读取其标准输入并应用于输入文件。
  • 首先,我们email_webdev通过搜索将 设为当前行:/email_webdev:/
  • 然后,从当前行开始,我们抓取 42 行块.,.+41d
  • 事情已经完成,所以现在我们保存并退出:x

PS:179-214范围不是42行。

相关内容