Grep для нескольких строк и нескольких строк, включая следующую строку - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь собрать 3 поля для строк a, b и c.Я знаю, что это можно сделать с помощью

grep -E 'a|b|c'

Однако я также хочу использовать grep для строк x, y и z, включая следующую строку.Я знаю, что это можно сделать с помощью

grep -A1 'x'

Итак, мой вопрос: возможно ли объединить все это в одну команду?Например, что-то вроде (я знаю, что эта команда не работает, просто пример)

grep -E 'a|b|c' -A1 'x|y|z'

Если есть лучший способ без grep или даже с использованием python, который был бы полезен, я просто прибегнул к использованию grepкак я думал, это будет быстрее, чем чтение файла строка за строкой с python.Ура!

РЕДАКТИРОВАТЬ: Итак, у меня есть большой файл с повторяющимися разделами, он выглядит примерно так:

{
    "source_name": [
        "$name"
    ],
    "source_line": [
        52
    ],
    "source_column": [
        1161
    ],
    "source_file": [
        "/somerandomfile"
    ],
    "sink_name": "fwrite",
    "sink_line": 55,
    "sink_column": 1290,
    "sink_file": "/somerandomfile",
    "vuln_name": "vuln",
    "vuln_cwe": "CWE_862",
    "vuln_id": "17d99d109da8d533428f61c430d19054c745917d0300b8f83db4381b8d649d83",
    "vuln_type": "taint-style"
}                      

И этот раздел между {} повторяется в файле.Итак, что я пытаюсь найти, это строка под source_name, source_line и source_file вместе с vuln_name, sink_file и sink_line.Поэтому пример вывода должен быть:

    "source_name": [
        "$name"
    "source_line": [
        52
    "source_file": [
        "/somerandomfile"
    "sink_line": 55,
    "sink_file": "/somerandomfile",
    "vuln_name": "vuln",

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

AWK

awk поддерживает шаблоны диапазона, которые соответствуют всему от pattern1 до pattern2:

awk '/(aaa|bbb|ccc)/,/[xyz]/' data.txt

PYTHON

Python позволяет вам скомпилировать регулярные выражения для скорости, и вы можете вызвать скрипт как одну команду, поместив его в файл.

import re

pattern1 = re.compile("a|b|c")
pattern2 = re.compile("x|y|z")
saw_pattern1 = False

with open("data.txt", "rb") as fin:
    for line in fin:
        if saw_pattern1 and pattern2.match(line):
            print("do stuff")
        saw_pattern1 = pattern1.match(line)
0 голосов
/ 20 ноября 2018

Этот скрипт Python должен быть в состоянии выполнить эту работу, и он допускает некоторую специальную настройку, которую было бы трудно получить в плотной команде grep:

my_grep.py

import re
import sys

first = re.compile(sys.argv[1])
second = re.compile(sys.argv[2])
with open(sys.argv[3]) as f:
  content = f.readlines()

for idx in range(len(content)):
  first_match = first.search(content[idx])
  if first_match:
    print(content[idx])
  second_match = second.search(content[idx])
  if second_match and (idx+1) < len(content):
    print(content[idx])
    print(content[idx+1])

Вы можете сгенерировать желаемый результат следующим образом:

 python my_grep.py 'sink_line|sink_file|vuln_name' 'source_name|source_line|source_file' input_file

Учитывая, что ваш входной файл называется input_file.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...