sed 仅删除第一个模式匹配
sed remove first pattern match only
我想在两个模式之间匹配一组数据并删除此数据和 start/end 模式,但仅针对第一次出现的模式。
所以如果这是测试数据:
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
TESTLINE1
TESTLINE2
TESTLINE3
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
这将很高兴删除所有模式匹配和中间的行,但我只想删除第一个模式匹配和中间的行:
sed '/PATTERNSTART/,/PATTERNEND/d' testsed.txt
输出:
TESTLINE1
TESTLINE2
TESTLINE3
所需输出:
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
TESTLINE1
TESTLINE2
TESTLINE3
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
任何 sed 想法?
使用
sed -e '/PATTERNSTART/,/PATTERNEND/d' -e '/PATTERNEND/q' some_file.txt
q
命令导致 sed
退出。
这机器有点不可思议,但它确实有效:
sed '/PATTERNSTART/,/PATTERNEND/ { // { x; s/$/./; x; }; x; /.../! { x; d; }; x; }' filename
如下:
/PATTERNSTART/,/PATTERNEND/ { # in the pattern range
// { # in the first and last line:
x
s/$/./ # increment a counter in the hold buffer by
# appending a character to it. The counter is
# the number of characters in the hold buffer.
x
}
x # for all lines in the range: inspect the
# counter
/.../! { # if it is not three or more (the counter
# becomes three with the start line of the
# second matching range)
x
d # delete the line
}
x
}
该代码中的 x
s 主要是为了确保在整个事情结束时计数器最终回到保持缓冲区中。 //
位有效,因为 //
重复最后一次尝试的正则表达式,这是第一行范围的起始模式和其他行的结束模式。
只需使用 awk(cat -n
只是为了让您可以看到正在打印的行号):
$ cat -n file | awk '/PATTERNSTART/{f=1;++c} !(f && c==1); /PATTERNEND/{f=0}'
6 PATTERNSTART
7 LINE1
8 LINE2
9 LINE3
10 PATTERNEND
11 TESTLINE1
12 TESTLINE2
13 TESTLINE3
14 PATTERNSTART
15 LINE1
16 LINE2
17 LINE3
18 PATTERNEND
将 c
上的测试设置为您要跳过的任何块的出现次数:
$ cat -n file | awk '/PATTERNSTART/{f=1;++c} !(f && c==2); /PATTERNEND/{f=0}'
1 PATTERNSTART
2 LINE1
3 LINE2
4 LINE3
5 PATTERNEND
11 TESTLINE1
12 TESTLINE2
13 TESTLINE3
14 PATTERNSTART
15 LINE1
16 LINE2
17 LINE3
18 PATTERNEND
你可以用那个来做这个(我承认很丑)sed 代码:
sed -e '/PATTERNSTART/,/PATTERNEND/{ /PATTERNEND/b after; d; :after; N; s/^.*\n//; :loop; n; b loop; }' testsed.txt
让我们仔细看看:
sed -e '/PATTERNSTART/,/PATTERNEND/{
/PATTERNEND/b after; # if we're at the end of match, go to the hack
d; # if not, delete the line and start a new cycle
:after; # Begin "end of part to delete"
N; # get the next line...
s/^.*\n//; # ...and forget about this one
# We now only have to print everything:
:loop; n; b loop;
# And you sir, have your code!
}' testsed.txt
这可能对你有用 (GNU sed):
sed '/PATTERNSTART/,/PATTERNEND/{x;/./{x;b};x;/PATTERNEND/h;d}' file
这使用保持 space 作为开关。检查文件中所需的行范围。如果遇到并且 hold space 不为空,则第一个范围已被删除,因此退出并正常打印。如果不是,将开关设置在最后一个模式匹配上并删除该范围内的所有行。
sed '/PATTERNSTART/,/PATTERNEND/{0,/PATTERNEND/d}' file
我想在两个模式之间匹配一组数据并删除此数据和 start/end 模式,但仅针对第一次出现的模式。
所以如果这是测试数据:
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
TESTLINE1
TESTLINE2
TESTLINE3
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
这将很高兴删除所有模式匹配和中间的行,但我只想删除第一个模式匹配和中间的行:
sed '/PATTERNSTART/,/PATTERNEND/d' testsed.txt
输出:
TESTLINE1
TESTLINE2
TESTLINE3
所需输出:
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
TESTLINE1
TESTLINE2
TESTLINE3
PATTERNSTART
LINE1
LINE2
LINE3
PATTERNEND
任何 sed 想法?
使用
sed -e '/PATTERNSTART/,/PATTERNEND/d' -e '/PATTERNEND/q' some_file.txt
q
命令导致 sed
退出。
这机器有点不可思议,但它确实有效:
sed '/PATTERNSTART/,/PATTERNEND/ { // { x; s/$/./; x; }; x; /.../! { x; d; }; x; }' filename
如下:
/PATTERNSTART/,/PATTERNEND/ { # in the pattern range
// { # in the first and last line:
x
s/$/./ # increment a counter in the hold buffer by
# appending a character to it. The counter is
# the number of characters in the hold buffer.
x
}
x # for all lines in the range: inspect the
# counter
/.../! { # if it is not three or more (the counter
# becomes three with the start line of the
# second matching range)
x
d # delete the line
}
x
}
该代码中的 x
s 主要是为了确保在整个事情结束时计数器最终回到保持缓冲区中。 //
位有效,因为 //
重复最后一次尝试的正则表达式,这是第一行范围的起始模式和其他行的结束模式。
只需使用 awk(cat -n
只是为了让您可以看到正在打印的行号):
$ cat -n file | awk '/PATTERNSTART/{f=1;++c} !(f && c==1); /PATTERNEND/{f=0}'
6 PATTERNSTART
7 LINE1
8 LINE2
9 LINE3
10 PATTERNEND
11 TESTLINE1
12 TESTLINE2
13 TESTLINE3
14 PATTERNSTART
15 LINE1
16 LINE2
17 LINE3
18 PATTERNEND
将 c
上的测试设置为您要跳过的任何块的出现次数:
$ cat -n file | awk '/PATTERNSTART/{f=1;++c} !(f && c==2); /PATTERNEND/{f=0}'
1 PATTERNSTART
2 LINE1
3 LINE2
4 LINE3
5 PATTERNEND
11 TESTLINE1
12 TESTLINE2
13 TESTLINE3
14 PATTERNSTART
15 LINE1
16 LINE2
17 LINE3
18 PATTERNEND
你可以用那个来做这个(我承认很丑)sed 代码:
sed -e '/PATTERNSTART/,/PATTERNEND/{ /PATTERNEND/b after; d; :after; N; s/^.*\n//; :loop; n; b loop; }' testsed.txt
让我们仔细看看:
sed -e '/PATTERNSTART/,/PATTERNEND/{
/PATTERNEND/b after; # if we're at the end of match, go to the hack
d; # if not, delete the line and start a new cycle
:after; # Begin "end of part to delete"
N; # get the next line...
s/^.*\n//; # ...and forget about this one
# We now only have to print everything:
:loop; n; b loop;
# And you sir, have your code!
}' testsed.txt
这可能对你有用 (GNU sed):
sed '/PATTERNSTART/,/PATTERNEND/{x;/./{x;b};x;/PATTERNEND/h;d}' file
这使用保持 space 作为开关。检查文件中所需的行范围。如果遇到并且 hold space 不为空,则第一个范围已被删除,因此退出并正常打印。如果不是,将开关设置在最后一个模式匹配上并删除该范围内的所有行。
sed '/PATTERNSTART/,/PATTERNEND/{0,/PATTERNEND/d}' file