代码之家  ›  专栏  ›  技术社区  ›  Enialis

用后续行(sed)中的信息替换行内容的Bash脚本

  •  0
  • Enialis  · 技术社区  · 3 年前

    我有一个File.txt,在方括号[]中的后续行中列出了几个项目和其他详细信息:

    item name1,
    item name2,
    item name3,
    item name4,
    some text
    on several lines
    detail name1;
    detail name2[moreinfo];
    detail name3[can contain numbers and characters:1];
    detail name4;
    

    我想修改它,使每个项目的详细信息都附加在前几行中,以具有以下预期输出:

    item name1,
    item name2[moreinfo],
    item name3[can contain numbers and characters:1],
    item name4,
    some text
    on several lines
    detail name1;
    detail name2[moreinfo];
    detail name3[can contain numbers and characters:1];
    detail name4;
    

    当项目数量未知时,有什么简单的sed表达式可以做到这一点吗? 我想要这样的东西:

    sed -i '/detail \(.*\)\[\(.*\)\]/ s/item \1/item \1\[\2\]/g' File.txt
    

    但我知道反向引用不是这样工作的。

    1 回复  |  直到 3 年前
        1
  •  4
  •   choroba    3 年前

    下面是一个Perl解决方案:

    perl -0777 -pe 's/^item (.*),(?=(?:.|\n)*^detail \1(\[.*\]))/item $1$2,/mg'
    

    它使用 -0777 (可以缩短为 -g 由于Perl5.36)将整个文件读取为单个字符串。替换使用 (?=...) 前瞻性断言来搜索相应的细节。

        2
  •  0
  •   Ed Morton    3 年前

    使用 tac 以及任何 awk :

    $ tac file |
        awk -F'[[ ,;]' '
            ($1 == "detail") && match($0,/[[].*]/) { det[$2] = substr($0,RSTART,RLENGTH) }
            ($1 == "item") && ($2 in det) { sub(/,$/,""); $0 = $0 det[$2] "," }
            { print }
        ' |
        tac
    item name1,
    item name2[moreinfo],
    item name3[can contain numbers and characters:1],
    item name4,
    some text
    on several lines
    detail name1;
    detail name2[moreinfo];
    detail name3[can contain numbers and characters:1];
    detail name4;