sed:在第一次匹配后删除 n 行

sed: delete n lines after first match

我想使用 sed 删除文本文件中第一个匹配项之后的 N 行。

(我知道大部分问题都用“使用awk”回答了,但我想用sed,不管它比awk强大多少。它是更多的是在一定的时间限制内,我目前最喜欢使用哪种工具)

我得到的最远的是:

sed -i "0,/pattern/{/pattern/,+Nd}" file.txt

思想是0,表示第一次出现,大括号在第一行搜索模式,删除N 发生后的行

尝试

sed '/pattern/{N;N;N;N;N;N;N;d;}' file.txt

0, 构造和您尝试使用的相对行号寻址特定于 GNU sed。便携式 sed 没有这些设施。

这将在 每个 匹配之后删除接下来的六行。如果您只想删除第一个出现的地方并保持文件的其余部分不变,可以添加一个单独的循环来简单地打印所有剩余的行。

您尝试的问题是 0,/pattern/ 将匹配限制为从第一次出现 /pattern/ 开始的行,但那是范围的末尾,因此此表达式选择的任何内容都无法运行在该范围之外的行上。

假设你的 shell 是 bash(问题最初有一个 bash 标签):

n=3
sed -f <(printf -v nsp '%*s' $n; printf '/%s/{x;/./!{s/^/./;h;%sd;};x;}\n' 'pattern' "${nsp// /N;}") file

请注意 n 是可变的(3 只是一个实例)并且构建的 sed 脚本不是特定于 GNU 的。

这可能适合您 (GNU sed):

sed '0,/pattern/{//{:a;N;s/\n/&/N;Ta;d}}' file

删除包含 pattern 的行,然后仅删除其后的 N 行。

选择:

sed '/pattern/{x;//{x;b};x;h;:a;N;s/\n/&/N;Ta;d}' file

N.B。替换命令后面的 N 指的是模式 space.

中第 n 次出现的换行符

更新 1:上述 sed 解决方案不普遍满足 objective 的示例:

cmd='/5=P$/{N;N;N;N;N;N;d;}'
echo "\n input ${b} :: \n\n———————\n" \
     "${b}\n--------------\n\n sed "    \
     "commands :: \n\n--------------\n " \
     "${cmd}\n--------------\n\n GNU sed "\
     "::\n\n$( gsed "${cmd}" <<< "${b}" )" \
     "\n\n BSD sed ::\n\n$( sed "${cmd}" <<< "${b}" )\n\n"

 input ${b} :: 

--------------
    84  77138=48001=P
    85  77138=48035=P
    86  77138=78118=P
    87  77138=79248=P
--------------

 sed commands :: 

--------------
 /5=P$/{N;N;N;N;N;N;d;}
--------------

 GNU sed ::

    84  77138=48001=P
    85  77138=48035=P
    86  77138=78118=P
    87  77138=79248=P

 BSD sed ::

    84  77138=48001=P

由于未知原因,当输入缺少超过模式的足够行时,

  • 此解决方案适用于 BSD sed
  • 但在 GNU sed 上完全失败。

==============================

sed 是必须满足的要求吗?你也可以用 awk 做 one-liners :

(故意冗长以准确展示匹配和跳过的行的样子):

# gawk profile, created Thu Apr 28 18:36:55 2022

# BEGIN rule(s)

BEGIN {
 1      printf "\n\t N :: %.f :: FS i.e. "\
               "pattern :: %*s\n\n", N = +N, ++__, FS = pattern
}

# Rule(s)

87  NF *= -(_+=(_= __<NF ? -__-N :_)^!__)<+_ { # 45
45      print
}


     1  77138=501=A
     2  77138=3413=A
     3  77138=3414=A
     4  77138=8624=A
     5  77138=19572=A
     6  77138=22220=A
     7  77138=23670=A
     8  77138=25413=A
     9  77138=26351=A
    10  77138=27340=A
    11  77138=29288=A
    12  77138=121060=A
    13  77138=123028=A
    14  77138=132081=A
    15  77138=135789=A
    16  77138=154341=A
    17  77138=155876=A
    18  77138=170871=A
    19  77138=178562=A
skipped ::     20   77138=185367=A
skipped ::     21   77138=196718=A
skipped ::     22   77138=196985=A
skipped ::     23   77138=200012=A
skipped ::     24   77138=207162=A
skipped ::     25   77138=228289=A
skipped ::     26   77138=244747=A
skipped ::     27   77138=284795=A
skipped ::     28   77138=294579=A
skipped ::     29   77138=299765=A
skipped ::     30   77138=317856=A
skipped ::     31   77138=318815=A
    32  77138=324570=A
    33  77138=408049=A
    34  77138=514403=A
    35  77138=1647865=A
    36  77138=1738771=A
    37  77138=3217183=A
skipped ::     38   77138=3222837=A
skipped ::     39   77138=3235292=A
skipped ::     40   77138=14957980=I
skipped ::     41   77138=1159=M
skipped ::     42   77138=1196=M
skipped ::     43   77138=1251=M
    44  77138=1252=M
    45  77138=4951=M
    46  77138=16740=M
    47  77138=71501=M
skipped ::     48   77138=137=P
skipped ::     49   77138=348=P
skipped ::     50   77138=518=P
skipped ::     51   77138=519=P
skipped ::     52   77138=520=P
skipped ::     53   77138=925=P
    54  77138=1363=P
    55  77138=1483=P
    56  77138=1814=P
    57  77138=2692=P
    58  77138=3540=P
    59  77138=3594=P
    60  77138=3682=P
    61  77138=3869=P
    62  77138=3940=P
skipped ::     63   77138=3977=P
skipped ::     64   77138=4025=P
skipped ::     65   77138=4252=P
skipped ::     66   77138=4396=P
skipped ::     67   77138=9501=P
skipped ::     68   77138=13006=P
    69  77138=18113=P
skipped ::     70   77138=20907=P
skipped ::     71   77138=31936=P
skipped ::     72   77138=34954=P
skipped ::     73   77138=37126=P
skipped ::     74   77138=37482=P
skipped ::     75   77138=40135=P
    76  77138=40206=P
    77  77138=41279=P
    78  77138=41280=P
    79  77138=46140=P
skipped ::     80   77138=46157=P
skipped ::     81   77138=46173=P
skipped ::     82   77138=46218=P
skipped ::     83   77138=47592=P
skipped ::     84   77138=48001=P
skipped ::     85   77138=48035=P
    86  77138=78118=P
    87  77138=79248=P
 

     N :: 5 :: FS i.e. pattern :: [7]=[AP]$

     1  77138=501=A
     2  77138=3413=A
     3  77138=3414=A
     4  77138=8624=A
     5  77138=19572=A
     6  77138=22220=A
     7  77138=23670=A
     8  77138=25413=A
     9  77138=26351=A
    10  77138=27340=A
    11  77138=29288=A
    12  77138=121060=A
    13  77138=123028=A
    14  77138=132081=A
    15  77138=135789=A
    16  77138=154341=A
    17  77138=155876=A
    18  77138=170871=A
    19  77138=178562=A
    32  77138=324570=A
    33  77138=408049=A
    34  77138=514403=A
    35  77138=1647865=A
    36  77138=1738771=A
    37  77138=3217183=A
    44  77138=1252=M
    45  77138=4951=M
    46  77138=16740=M
    47  77138=71501=M
    54  77138=1363=P
    55  77138=1483=P
    56  77138=1814=P
    57  77138=2692=P
    58  77138=3540=P
    59  77138=3594=P
    60  77138=3682=P
    61  77138=3869=P
    62  77138=3940=P
    69  77138=18113=P
    76  77138=40206=P
    77  77138=41279=P
    78  77138=41280=P
    79  77138=46140=P
    86  77138=78118=P
    87  77138=79248=P

更简洁一点,就是

mawk -v pattern='[7]=[AP]$' -v N='5' -- '
BEGIN { 
      ++__ 
   FS = pattern 
} NF *= -(_+=(_=__<NF?-__-N:_)^!__) < +_' 

awk one-liner style

mawk 'NF*=-(_+=(_=1<NF?-1-N:_)^0)<+_' FS='[7]=[AP]$' N=5