sed 更改标签并保留部分内容

sed 更改标签并保留部分内容

我有一个大文本文件,其中多次出现包含 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。这是批判的这些字符不会出现在文件中。由于这些很难输入,我将使用几个变量se作为开始和结束标记。我用来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" "$@"

用法

保存此脚本,使其可执行,然后运行它,将数据文件作为参数并将输出重定向到临时文件。检查临时文件。

相关内容