我有一个 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行。