簡體   English   中英

如何到達文本文件的特定部分然后搜索

[英]How to do reach specific section of text file and then search

我有一個文本文件

Apples
Big 7
Small 6

Apples
Good 5
Bad 3

Oranges
Big 4
Small 2
Good 1
Bad 5

如何到達此文件的特定部分,然后執行grep? 例如,如果我需要查找有多少個好橘子,如何使用awk在命令行中以該文件作為輸入來執行?

您可以像這樣使用范圍運算符:

awk '/Apples/,/^$/ { if (/Good/) print $2}' file

將打印出多少個好蘋果:

5

當滿足第一個條件時,范圍運算符會評估為true,直到第二個條件都為true。 第二個模式/^$/匹配空行。 這意味着將僅對相關部分的“好”,“壞”等屬性進行測試。


我假設您的原始輸入文件不是雙倍行距的? 如果是這樣,可以修補上面的方法以跳過其他每行:

awk '!NR%2{next} /Oranges/,/^$/ { if (/Good/) print $2}' file

當記錄號NR為偶數時,NR%2為0!0為真,因此將跳過其他所有行。

當您具有名稱/值對時,通常最好首先構建一個按名稱索引並包含值的數組,然后您可以使用適當的名稱對索引進行索引,然后打印任何您感興趣的內容:

$ awk 'NF==1{key=$1} {val[key,$1]=$2} END{print val["Oranges","Good"]}' file
1

$ awk 'NF==1{key=$1} {val[key,$1]=$2} END{print val["Apples","Bad"]}' file
3

或者,如果您正在尋找實施一套更完整/更復雜的要求的起點,則可以采用以下一種方法:

$ awk '
NF {
    if (NF==1) {
        key=$1
        keys[key]
    }
    else {
        val[key,$1]=$2
        names[$1]
    }
}
END {
    for (key in keys)
        for (name in names)
            print key, name, val[key,name]
}
' file
Apples Big 7
Apples Bad 3
Apples Good 5
Apples Small 6
Oranges Big 4
Oranges Bad 5
Oranges Good 1
Oranges Small 2

為了測試@JohnB的理論,即如果有成千上萬個文件,shell腳本要比awk腳本快,我將OP輸入文件復制了5,000次到tmp目錄中,然后在它們上運行了這兩個等效腳本(基於Johns的bash腳本)在該線程中回答,然后執行與bash相同的awk命令):

$ cat tst.sh
for file in "$@"; do
    while read -r field1 field2 ; do
        [ -z "$field2" ] && name="$field1"
        case $name in
            Oranges) [ "$field1" = "Good" ] && echo "$field2";;
        esac
    done < "$file"
done

$ cat tst.awk
NF==1 { fruit=$1 }
fruit=="Oranges" && $1=="Good" { print $2 }

這是在這5,000個文件上同時運行的結果:

$ time ./tst.sh tmp/* > bash.out
real    0m6.490s
user    0m2.792s
sys     0m3.650s

$ time awk -f tst.awk tmp/* > awk.out
real    0m2.262s
user    0m0.311s
sys     0m1.934s

2個輸出文件相同。

您可以使用Bash在循環中逐行讀取文件。

while read -a fruit; do
    [ ${#fruit[@]} -eq 1 ] && name=${fruit[0]}
    case $name in
        Oranges) [ "${fruit[0]}" = "Good" ] && echo ${fruit[1]};;
    esac
done < file

您也可以將此函數設為函數並傳遞參數以獲取有關任何水果的特征信息。

read_fruit (){
    while read -a fruit; do
        [ ${#fruit[@]} -eq 1 ] && name=${fruit[0]}
        case $name in
            $1) [ "${fruit[0]}" = "$2" ] && echo ${fruit[1]};;
        esac
    done < file
}

采用:

read_fruit Apples Small

結果:

6

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM