bash - printf用法 - sed用法




如何根據條件從數據塊中獲取特定的數據 (5)

你的問題似乎是:

我無法將RS設置為[group] ,這既失敗RS="[group]"RS="\[group\]"

他說:

RS="[[]group[]]"

應該產生期望的結果。

我有這樣的文件:

[group]
enable = 0
name =  green
test = more

[group]
name  = blue
test = home

[group]
value = 48
name = orange
test = out

label和=和value之間可能有一個或多個空格/製表符。
每一個區塊的行數可能都很小心。
我喜歡有這個name ,只有當這不是真正的enable = 0

所以輸出應該是:

blue
orange

這是我設法創造的:

awk -v RS="group" '!/enable = 0/ {sub(/.*name[[:blank:]]+=[[:blank:]]+/,x);print $1}'
blue
orange

這有幾個錯誤:

  1. 我無法將RS設置為[group] ,這既失敗RS="[group]"RS="\[group\]" 。 如果name或其他標籤包含group則會失敗。
  2. 我不希望使用多個字符的RS ,因為這只是gnu awk

任何人有其他建議? sedawk而不是使用一長串的命令。


在這些情況下,記錄中有明確的name = value語句,我喜歡先用這些映射填充一個數組,例如:

map["<name>"] = <value>

然後使用這些名稱來引用我想要的值。 在這種情況下:

$ awk -v RS= -F'\n' '
{
    delete map
    for (i=1;i<=NF;i++) {
        split($i,tmp,/ *= */)
        map[tmp[1]] = tmp[2]
    }
}
map["enable"] !~ /^0$/ {
    print map["name"]
}
' file
blue
orange

如果您的awk版本不支持刪除整個數組,則將delete map更改為split("",map)

與使用RE和/或sub()等相比,如果您想比較和/或打印未來其他字段的值,它使得解決方案更加健壯和可擴展。


如果您知道組總是由空行分隔,請將RS設置為空字符串:

$ awk -v RS="" '!/enable = 0/ {sub(/.*name[[:blank:]]+=[[:blank:]]+/,x);print $1}'
blue
orange

@devnull在他的回答中解釋說,GNU awk也接受RS正則表達式,所以如果它在自己的行上,那麼你只能在[group]分割:

gawk -v RS='(^|\n)[[]group]($|\n)' '!/enable = 0/ {sub(/.*name[[:blank:]]+=[[:blank:]]+/,x);print $1}'

這確保我們不會像邪惡的名字分裂

[group]
enable = 0
name =  [group]
name = evil
test = more

既然你有行分隔記錄,你應該考慮把段落模式的awk 。 如果您必須測試[group]標識符,只需添加代碼來處理。 以下是一些應該滿足您的要求的示例代碼。 運行如下:

awk -f script.awk file.txt

script.awk內容:

BEGIN {

    RS=""
}

{
    for (i=2; i<=NF; i+=3) {

        if ($i == "enable" && $(i+2) == 0) {

            f = 1
        }

        if ($i == "name") {

            r = $(i+2)
        }
    }
}

!(f) && r {

    print r
}

{
    f = 0
    r = ""
}

結果:

blue
orange

這可能適用於你(GNU sed):

sed -n '/\[group\]/{:a;$!{N;/\n$/!ba};/enable\s*=\s*0/!s/.*name\s*=\s*\(\S\+\).*/\1/p;d}' file

如果enable變量未設置為0則將[group]塊讀入模式空間,然後將顏色替換掉。

  • sed -n '...'將sed設置為在靜音模式下運行,除非指定了pP命令,否則不輸出
  • /\[group\]/{...}當我們有一個包含[group]的行時,可以在大括號內找到它。
  • :a;$!{N;/\n$/!ba}做一個循環,我們需要一個地方來循環, :a是循環的地方。 $是文件地址和$!的結尾 意味著不是文件的結尾,所以$!{...}意味著當它不是文件的結尾時,在花括號裡面找到它。 N追加一個換行符,將下一行添加到當前行和/\n$/ba當我們有一個以空行分支( b )結束的行時。 因此,它將包含`[group]的行的所有行收集到空行(或文件的結尾)。
  • /enable\s*=\s*0/!s/.*name\s*=\s*\(\S\+\).*/\1/p如果收集的行包含enable = 0則不要替換掉顏色。 或者換句話說,如果到目前為止收集的行包含enable = 0 替換掉顏色。






awk