我想在两种模式之间匹配一组数据,并删除此数据和开始/结束模式,但仅限于第一次出现模式。
所以如果这是测试数据:
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想法?
答案 0 :(得分:3)
它有点令人难以置信,但是这很有效:
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
主要是为了确保当整个事情结束时计数器最终返回到保持缓冲区。 //
位有效,因为//
重复上一次尝试的正则表达式,这是第一行的范围的起始模式和其他的结束模式。
答案 1 :(得分:3)
只需使用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
答案 2 :(得分:1)
sed '/PATTERNSTART/,/PATTERNEND/{0,/PATTERNEND/d}' file
答案 3 :(得分:0)
你可以这样做(我承认非常难看)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
答案 4 :(得分:0)
这可能适合你(GNU sed):
sed '/PATTERNSTART/,/PATTERNEND/{x;/./{x;b};x;/PATTERNEND/h;d}' file
这使用保持空间作为开关。检查文件中是否有所需的行范围。如果遇到并且保持空间不为空,则第一个范围已被删除,因此挽救并正常打印。如果没有,请将开关设置为最后一个模式匹配并删除该范围内的所有行。
答案 5 :(得分:-1)
使用
sed -e '/PATTERNSTART/,/PATTERNEND/d' -e '/PATTERNEND/q' some_file.txt
q
命令导致sed
退出。