shell 将以specific_text_a开头的行移到以specific_text_b开头的行之下

vbkedwbf  于 2023-03-30  发布在  Shell
关注(0)|答案(2)|浏览(73)

我正在尝试移动一个现有的行,该行以let's say开头:abc::位于文件夹中各个md文件中以id:开头的现有行下面。
我们假设文件是这样的

(file 1)
 text
 id: 123
 more text
 abc:: cba
(file 2)
 text
 id: 321
 more text
 a lot more text
 abc:: def

在这两种情况下,运行代码的结果都应该是abc::...移动到id:...的正下方
我的假设是,下面的代码会将以abc::开始的行移动到包含id:的行的正下方。但是,如果我运行代码,它会运行文件(根据编辑的时间戳),但不会改变任何内容。
MWE:

find . -name '*.md' -type f -exec sed -i '' '/^id:/{
N
s/\n\(abc::.*\)/\1\
/
}' {} +
v8wbuo2f

v8wbuo2f1#

这个sed命令(通过find-exec执行)应该可以做到这一点:

find . -name '*.md' -type f -exec sed -i '' '
/^id:/,/^abc::/{
    /^id:/b
    /^abc::/{p; x; s/.//p; d;}
    ${x; s/.//p; x; p; d;}
    H; d
}' {} +
lrpiutwd

lrpiutwd2#

使用任何awk,包括MacOS上默认的BSD awk:

$ head *.md
==> file1.md <==
text
id: 123
more text
abc:: cba

==> file2.md <==
text
id: 321
more text
a lot more text
abc:: def
$ find . -type f -name '*.md' -exec awk '
    FNR == 1 { prt() }
    { all[++n] = $0 }
    /^abc::/ { src = n }
    /^id:/   { dst = n }
    END { prt() }

    function prt(    i) {
        for ( i=1; i<=n; i++ ) {
            if ( (i != src) || (dst == 0) ) {
                print all[i] > fname
            }
            if ( (i == dst) && (src != 0) ) {
                print all[src] > fname
            }
        }
        close(fname)
        fname = FILENAME
        src = dst = n = 0
    }
' {} +
$ head *.md
==> file1.md <==
text
id: 123
abc:: cba
more text

==> file2.md <==
text
id: 321
abc:: def
more text
a lot more text

即使abc::行出现在输入中的id:行之前,如果其中一行没有出现在输入中,它也会按原样打印文件。

相关问题