我有一个大文本文件,其中多次出现包含 URL 的标记:
[tag]https://example.com/222389/link/11835457224168404[/tag]
我需要按如下方式重新格式化标签:
[new-tag]11835457224168404[/new-tag]
(仅捕获“link”之后的 url 部分(“id”)并将标签修改为“new-tag”:
- 每行可以有多个标签;
- 标签位置并不统一 - 它们在整个文件中随机出现;
- 标签内容开头可以有一个空格('http'),使用'http://"或'https://',有时也使用'www';
标签偶尔在末尾(“id”之后)有内容或空格,如下所示:
[tag]https://example.com/222389/link/11835457224168404/qwertyiop[/tag]
或者
[tag]https://example.com/222389/link/11835457224168404?link=11835457224168401 [/tag]
有时,需要忽略单独出现的“[tag]”(没有结束的 [/tag] 或“http”)。
我如何使用 sed 或替代方案来做到这一点?
答案1
战略
虽然可以编写正则表达式不匹配多字符字符串,它们会变得复杂。我们将使用一个技巧将[tag]
和转换[/tag]
为单个字符,然后使用否定字符类。在此脚本中,我将使用 control-a 和 control-b。这是批判的这些字符不会出现在文件中。由于这些很难输入,我将使用几个变量s
和e
作为开始和结束标记。我用来notend
表示不是结束标记的任何字符序列。
#!/bin/bash
s=$'\001' # control-a, for the start tag
e=$'\002' # control-b, for the end tag
notend="[^$e]*" # expression for not the end tag.
# Program, Change the tags into single characters
# change matched pairs of tags into new form
# convert any unmatched tags back to original form
prog='
s:\[tag]:'"$s"':g
s:\[/tag]:'"$e"':g
s:'"$s$notend"'/link/\([0-9]*\)'"$notend$e"':[new-tag]\1[/newtag]:g
s:'"$s"':[tag]:g
s:'"$e"':[/tag]:g'
# run sed, passing any parameters
sed -e "$prog" "$@"
用法
保存此脚本,使其可执行,然后运行它,将数据文件作为参数并将输出重定向到临时文件。检查临时文件。