otherdata
otherdata
start_data
one
two
three
four
end_data
otherdata
otherdata
结果输出应该是:
one
two
three
four
sed
对我来说这看起来像是一份工作:
sed -n '/start_data/,/end_data/{1d;$d;p}' myfile
不工作。第一行被删除,但最后一行没有被删除! (到目前为止我无法用逻辑解释任何原因)
好吧,让我们尝试一下丑陋的方法:
sed -n '/start_data/,/end_data/{/start_data\|end_data/!p}' myfile
公平地说,这有效。但我想让更短的方法也能发挥作用,因为结果输出将总是在第一行和最后一行包含两种模式,因为我们只提取中间的数据。
为什么sed
尝试将1d
and$d
语句组合在花括号中会令人窒息?
答案1
您可以反转逻辑:
sed '1,/start_data/d;/end_data/,$d'
假设start_data
不在第一行。要解决这个问题,如果您有 GNU sed
,您可以改为:
sed '0,/start_data/d;/end_data/Q'
那0
和Q
是 GNU 特定的。Q
退出sed
而不打印模式空间,因此这也将使其更加高效,因为它不会像第一个解决方案那样继续读取和丢弃文件的其余部分。
答案2
awk
似乎很适合这个问题:
$ awk '/end_data/{f=0;};f{print;};/start_data/{f=1;}' myfile
one
two
three
four
上面使用标志f
来决定是否应该打印一行。当 时start_data
,标志设置为 true (1)。当end_data
找到时,该标志被设置为假(0)。当f
为 true 时,将打印该行。
为什么 sed 在尝试将 1d 和 $d 语句组合在花括号中时会窒息?
这不是“窒息”。它只是1d
指$d
文件中的第一行和最后一行,而不是模式中的第一行和最后一行。
答案3
嗯,这有效:
sed -ne/start_data/!d\;:n -e'n;/end_data/q;p;bn' <in
它甚至不会尝试p
rint ,直到遇到/start_pattern/
并且从该地址一直到最后一行,如果换行符拉入 matches ,它将用n
ext, uit 输入完全替换当前行,否则rint 。这就是全部。根据您的示例数据,输出为:q
/end_data/
p
one
two
three
four
它不会将一行识别为end_data
如果它也匹配第一个则匹配start_data
输入中出现的行。
答案4
在这里,让我对问题中提供的输入文件进行简单的修饰修改:
% cat myfile
red
orange
start_data
one
two
three
four
end_data
yellow
green
我只是otherdata
用不同的其他数据替换了这些行,因此我们可以通过内容唯一地引用输入文件中的每一行,而不必说“第一行”,因为这显然会受到误解,或者“第一行otherdata
” ”,这有点冗长(而且据我所知,也可能会受到误解)。
现在,您可能会发现与第一次尝试最接近的事情是
% sed -n '/start_data/,/end_data/p' myfile | sed '1d;$d'
one
two
three
four
你的第一次尝试 ( sed -n '/start_data/,/end_data/{1d;$d;p}' myfile
) “窒息”,因为(正如 John1024 所说) line1
是red
行*
,而 line$
是green
行**。没有1d;$d;
任何效果,因为这些行(事实上,全部/colordata行otherdata
)已被/start_data/,/end_data/
范围排除。
__________
* 即,第一行全部的输入文件,不仅仅是匹配的范围
**,即最后一行全部的输入文件,不仅仅是匹配范围
顺便问一下,您是说您的命令产生了以下输出吗?
one
two
three
four
end_data
因为这没有意义,除非start_data
曾是第 1 行(即,如果red
和orange
不存在)。