BASH - читать строки из раздела файла - PullRequest
0 голосов
/ 15 октября 2019

У меня есть файл, отформатированный так:

[SITE1]
north
west

[MOTOR]
west
south
north

[AREA]
west
east
north

[CLEAR]

Что мне нужно сделать, это прочитать все значения из определенного раздела.

Например: прочитать AREA и вернуться:

west
east
north

Примеры, которые я нашел в Интернете, относятся к файлам ini, в которых есть пары ключ-значение. Кто-нибудь может помочь посоветовать, как мне это сделать?

Спасибо

Ответы [ 3 ]

2 голосов
/ 15 октября 2019

Использование sed:

category=MOTOR; sed -nE "/^\[$category\]$/{:l n;/^(\[.*\])?$/q;p;bl}" /path/to/your/file

Он ничего не делает, пока не совпадет со строкой, соответствующей вашей целевой категории, и в этот момент он входит в цикл. В этом цикле он потребляет строку, завершается, если это пустая строка или другая категория (или конец файла), и печатает строку другим способом.

Используются следующие команды sed:

  • /pattern/ выполняет следующую команду или группу команд, когда текущая строка соответствует шаблону
  • {commands} группирует команды, например, для их условного выполнения.
  • :l определяет метку с именем "l", к которой вы сможете перейти.
  • n просит sed начать работу на следующей строке.
  • q выход
  • p печатает текущую строку
  • bl переход на метку "l"

Вы можете попробовать здесь .

2 голосов
/ 15 октября 2019

Имеется в виду два варианта - использовать фильтр (например, awk, sed) для извлечения соответствующего раздела или использовать bash для фильтрации в конкретном разделе.

С помощью bash, используяфункция:

#! /bin/bash

function read_section {
    local id=$1
    local match
    input=()
    while read p ; do
        if [ "$p" = "[$id]" ] ; then
            # Read data here
            while read p ; do
                # Check for end of section - empty line
                if [ "$p" = "" ] ; then
                    break
                fi
                # Do something with '$p'
                input+=("$p")
                echo "Item $p"
            done
            # Indicate section was found
            return 0
        fi
    done
    # Indicate section not found
    return 1
}

if read_section "AREA" < p.txt ; then
        echo "Found Area" "${#input[$@]}"
else
        echo "Missing AREA"
fi

if read_section "FOO" < p.txt ; then
        echo "Found FOO"
else
        echo "Missing FOO"
fi

Вывод: (помещение образца ввода в файл свойств p.txt)

Item west
Item east
Item north
Found Area 4
Missing FOO

Примечания

  1. , что не ясно, если каждыйраздел заканчивается пустой строкой. Код предполагает, что это так. В противном случае изменение раздела может быть изменено на if [[ "$p" = \[* ]] или аналогичное с дополнительной проверкой, чтобы игнорировать пустую строку.
  2. Функция возвращает true / false, чтобы указать, был ли найден раздел. Сценарий может воздействовать на эту информацию.
  3. Загруженные элементы помещаются во входной массив для дальнейшей обработки
0 голосов
/ 15 октября 2019

Альтернативой является использование внешней программы для фильтрации ввода. Это МОЖЕТ обеспечить преимущество в производительности, если входной файл ОЧЕНЬ большой или если необходима дополнительная логика.

function filter_section {
    local id=$1
    awk -v ID="$id" '/^\[/ { p= ($0 == "[" ID "]" ); next } p && $0 { print }' < p.txt
}

function read_section {
    local id=$1
    local match
    input=()
    while read p ; do
        # Do something with '$p'
        input+=("$p")
        echo "Item $p"
    done <<< $(filter_section "$id")
    # Indicate section not found
    [ "${#input[*]}" -gt 0 ] && return 0
    return 1
}

if read_section "AREA" < p.txt ; then
        echo "Found Area" "${#input[$@]}"
else
        echo "Missing AREA"
fi

if read_section "FOO" < p.txt ; then
        echo "Found FOO"
else
        echo "Missing FOO"
fi

...