如何在两种模式之间划线

时间:2014-06-06 11:11:11

标签: regex bash sed

我有一个这样的文件:

  

a sth1
  一个sth2
  b sth3
  b sth4
  c sth5
  c sth6
  c sth6
  d sth8
  d sth9
  d sth10
  X sth10
  X sth11

我想知道从b开始的第一行和以d开头的最后一行之间的所有行:

  

b sth3
  b sth4
  c sth5
  c sth6
  c sth6
  d sth8
  d sth9
  d sth10

我有一个sed命令sed -n /"b"/,/"d"/p final.txt,但输出是:

  

b sth3
  b sth4
  c sth5
  c sth6
  c sth6
  d sth8

我的问题是如何修改sed命令以获得预期的结果?

我很抱歉不准确。我应该问一下这个问题:

我有一个这样的文件:

  

127.0.0.1 - - [04 / Jun / 2014:11:21:01 +0200] STH1
  127.0.0.1 - - [04 / Jun / 2014:11:21:01 +0200] STH2
  127.0.0.1 - - [04 / Jun / 2014:11:21:01 +0200] STH3
  127.0.0.1 - - [04 / Jun / 2014:12:21:01 +0200] STH4
  127.0.0.1 - - [04 / Jun / 2014:12:21:01 +0200] STH5
  127.0.0.1 - - [04 / Jun / 2014:12:21:01 +0200] STH6
  127.0.0.1 - - [04 / Jun / 2014:12:21:01 +0200] STH7
  127.0.0.1 - - [04 / Jun / 2014:13:21:01 +0200] STH8
  127.0.0.1 - - [04 / Jun / 2014:13:21:01 +0200] STH9
  127.0.0.1 - - [04 / Jun / 2014:13:21:01 +0200] STH10
  127.0.0.1 - - [04 / Jun / 2014:14:21:01 +0200] STH11
  127.0.0.1 - - [04 / Jun / 2014:14:21:01 +0200] STH12
  127.0.0.1 - - [04 / Jun / 2014:15:21:01 +0200] STH13
  127.0.0.1 - - [04 / Jun / 2014:15:21:01 +0200] STH14

我希望在包含$startDate="04/Jun/2014:12:21:01"的第一行和包含$endDate="04/Jun/2014:13:21:01"的最后一行之间提取内容。结果应该是:

  

127.0.0.1 - - [04 / Jun / 2014:12:21:01 +0200] STH4
  127.0.0.1 - - [04 / Jun / 2014:12:21:01 +0200] STH5
  127.0.0.1 - - [04 / Jun / 2014:12:21:01 +0200] STH6
  127.0.0.1 - - [04 / Jun / 2014:12:21:01 +0200] STH7
  127.0.0.1 - - [04 / Jun / 2014:13:21:01 +0200] STH8
  127.0.0.1 - - [04 / Jun / 2014:13:21:01 +0200] STH9
  127.0.0.1 - - [04 / Jun / 2014:13:21:01 +0200] STH10

$startDate$endDate是BASH脚本中的变量。我真的为我的上一篇文章道歉,我问的不是精确的问题......

7 个答案:

答案 0 :(得分:4)

awk one-liner

如果您的文件已按第1列(a, b, c...)排序,则适用于您的示例:

awk '$1>="b"&&$1<="d"' file

此处的"b""d"可能是其他字符串,例如abczzz,只要文件已排序,它就可以正常工作。

添加sed one-liner:

根据你的例子,这个sed行在这里工作:

sed  -n '/^b/,/^d/{/^[^d]/p};/^d/p' file

答案 1 :(得分:0)

以下是awk中的一种方式:

awk '/^b/{p=1} /^d/{p=2} p==2 && substr($1, 1, 1) != "d" {exit} p' file
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

答案 2 :(得分:0)

这是awk

awk '/^b/ {f=1} /^d/ {g=1} g && !/^d/ {f=0} f' file
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

答案 3 :(得分:0)

使用此sed命令获取预期结果。

 $ sed -n '/^b/,/^d/{p;d};/^d/p' `input_filename`

答案 4 :(得分:0)

如果您的文件未排序,则需要循环两次:首先要知道要打印的行然后打印它们:

$ awk 'FNR==NR {if (/^b/ && !b) {b=NR} if (/^d/) {d=NR}; next} (FNR>=b && FNR<=d)' file file
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

根据评论,如果您想将bd定义为可以使用的参数:

-v start="your_start_date"
-v end="your_end_date"

查看包含当前数据的示例:

$ awk -v start="b" -v end="d" 'FNR==NR {if ($1 == start && !b) {b=NR} if ($1 == end) {d=NR}; next} (FNR>=b && FNR<=d)' file file
b sth3
b sth4
c sth5
c sth6
c sth6
d sth8
d sth9
d sth10

根据您的上次更新:

$ startDate="04/Jun/2014:12:21:01"
$ endDate="04/Jun/2014:13:21:01"

$ awk -v start="$startDate" -v end="$endDate" 'FNR==NR {if ($0 ~ start && !b) {b=NR} if ($0 ~ end) {d=NR}; next} (FNR>=b && FNR<=d)' file file
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH4
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH5
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH6
127.0.0.1 - - [04/Jun/2014:12:21:01 +0200] STH7
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH8
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH9
127.0.0.1 - - [04/Jun/2014:13:21:01 +0200] STH10

答案 5 :(得分:0)

如果你不介意grep

grep "^[b-d]" file

答案 6 :(得分:0)

sed -n '/^b/p;/^c/p;/^d/p' YourFile

假设它与您的样本类似。使用bd

处理缺失的行