BASH - 从文件部分读取行

问题描述 投票:0回答:3

我有一个格式如下的文件:

[SITE1]
north
west

[MOTOR]
west
south
north

[AREA]
west
east
north

[CLEAR]

我需要做的是读取特定部分的所有值。

例如:读取AREA并返回:

west
east
north

我在网上找到的例子是ini文件,它有键值对。 谁能帮我建议一下我该怎么做?

谢谢

bash file parsing
3个回答
3
投票

使用

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
投票

记住两个选项 - 使用过滤器(例如,

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
投票

另一种方法是使用外部程序来过滤输入。如果输入文件非常大,或者需要额外的逻辑,这可能会提供性能优势。

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

© www.soinside.com 2019 - 2024. All rights reserved.