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
我想使用 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.
更新 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