仅当pattern1和pattern2在连续行中匹配时如何grep

时间:2013-12-05 10:01:50

标签: grep

我有一个如下文件:

city-italy
good food
bad climate
-
city-india
bad food
normal climate
-
city-brussel
normal dressing
stylish cookings
good food
-

问题 - 我想grep cityfood,因为“食物”是“坏”。

例如 - 对于上面的问题,我需要一个grep命令来得到如下的答案

city-india
bad food

请帮助我,如果两者并行成功,我将如何获得模式1和模式2。

我的意思是两个模式应该匹配,它应该在下一行中grep。

6 个答案:

答案 0 :(得分:6)

您可以使用管道执行此操作 - grep -A1 city <filename> | grep -B1 "bad food"cat filename | grep -A1 city | grep -B1 "bad food"(或管道的任何其他流源)

答案 1 :(得分:1)

如果保证城市名称在食品质量之前(允许其间的任何其他信息):

sed -n -e '/^city/h' -e '/bad food/{x;G;p}' input

将每个城市的名称保留在保留缓冲区中,并在匹配不良食物时打印最后一个城市名称。

答案 2 :(得分:0)

使用bad food(由于RS)

获取gnu awk城市
awk '/bad food/ {print RS $1}' RS="city" file
city-india

答案 3 :(得分:0)

另一个awk系列:

kent$  awk 'BEGIN{FS=OFS="\n";RS="-"FS}/bad food/{print $1,$2}' file
city-india
bad food

答案 4 :(得分:0)

如果确保订单,您可以直接使用命令grep和OR:

grep -e "city" -e "food" FILE_INPUT

然后希望这个城市将遵循其食物特征。

结果如下:

city-italy
good food
city-india
bad food
city-brussel
good food

您可以更改模式以获得更多过滤结果。

答案 5 :(得分:0)

I know this is an old question, but here's a "robust" alternative (cuz I'm into that):

grep -x -e'city-.*' -e'good food' -e'bad food' -e'-' | tr \\n \| | sed -e's/|-|/\n/g' | grep -xe'[^|]\+|[^|]\+' | grep -e'|bad food$' | tr \| \\n

Explanation

  1. grep -x -e'city-.*' -e'good food' -e'bad food' -e'-': only keep the lines that contain a "city line", a "food line" (either good or bad), or a "separator line" (the food line expression could be better, I know), the -x argument to grep will make it return a line only if the whole line matches the given expression (incidentally, this first stage makes the whole pipe not choke on differently-sized "registers"),

  2. tr \\n \|: turn newlines into pipes (you can use any character that does not appear in the original file, pipe works, so does a colon, you get the idea),

  3. sed -e's/|-|/\n/g': replace the |-| string by a newline (this are the places we know a "register" ends, since we only kept the datums we're interested in and the separators, we know that now we have each of our "registers" in a single line, with their fields separated by pipes),

  4. grep -xe'[^|]\+|[^|]\+': only keep lines containing exactly two fields (ie. the city and food fields),

  5. grep -e'|bad food$': keep only lines ending in |bad food,

  6. tr \| \\n: turn pipes back into newlines (nb. this is just here so that the output conforms to the question's specification, it's not really needed, nor preferred in my opinion).

Partial outputs

After grep -x -e'city-.*' -e'good food' -e'bad food' -e'-':

city-italy
good food
-
city-india
bad food
-
city-brussel
good food
-

After tr \\n \|:

city-italy|good food|-|city-india|bad food|-|city-brussel|good food|-|

After sed -e's/|-|/\n/g':

city-italy|good food
city-india|bad food
city-brussel|good food

After grep -xe'[^|]\+|[^|]\+': idem, since we don't have a "city line" without a "food line" in the example given, nor a register containing two "city lines" and a "food line", nor a register containing a "city line" and two "food lines", nor... you get the picture,

After grep -e'|bad food$':

city-india|bad food

After tr \| \\n:

city-india
bad food

Why is this more "robust"?

The input file basically consists of different "registers", each containing a variable number of "fields", but instead of having them in an "horizontal" format, we find them in a "vertical" one, ie. one field per line with a lone - separating whole registers.

The pipe above supports any amount of fields in each register, it only assumes that:

  1. Registers are separated by a lone -,

  2. The "city fields" are all of the form city-*,

  3. The "food fields" are either good food or bad food,

  4. If at all existent, "city" fields appear before "food" fields.

(this last one I find particularly hard to relax, at least in a "normal"-ish pipe like the one given).

I does not assume that:

  1. Each register has a "city" and a "food" field,

  2. Each register has only "city" and "food" fields.

Disclaimer

I'm not claiming this is in any way better than any of the other answers, it's just that I can't do sed or awk to save my own life, and often find pipes like this are helpful in understanding how the file gets filtered and transformed.

All in all, it's just a matter of taste.