web-dev-qa-db-ja.com

CSVから2列の値を検索する

私は、例えば20の奇数列を持つcsvファイルを持っています。

14番目と15番目の列の値を取得する必要があります。14番目の列の値は"VALUE1"で、15番目の列の値は"VALUE2"です。

14番目の列にVALUE1があり、15番目の列にVALUE2がある場合にのみ、条件が満たされます。集計数を取得する必要があります。

wc -lはカウントリストを提供し、cut -d "," -f14,15は14番目と15番目の列の値を提供すると思います。しかし、14日にはVALUE1があり、15日にはVALUE2があるかどうかを確認する方法は?

以下のものはうまくいくと思います

grep -r "" * | cut -d " " -f14,15 | grep "Value1" | grep "Value2"

それでも、これが完璧な方法だとは思いません。

5
Ebbu Abraham

awkの方が便利かもしれません。

例えば:

$> echo "a b c d e" | awk '$2=="b" && $3=="c" {print}'
a b c d e

$> echo "a b c d e" | awk '$2=="a" && $3=="c" {print}'

$> echo "a b c d e" | awk '$2=="b" && $3=="d" {print}'

だからあなたの質問への答えは次のようになります:

awk '$14=="VALUE1" && $15=="VALUE2" {print}'

awkが利用できない場合は、cutgrepおよびwcを使用して実行できます。

$ echo -e 'a,b, c,d\na,val1 ,val2,c' \
   | cut -d ',' -f2,3 | grep '^ *val1 *, *val2 *$' | wc -l

,区切り文字として(そして何とかエスケープされていない,が含まれています)。テストのために、14と15の代わりに列2と3が使用されます。

grepパターンでは、値の前後に空白を付けることができます(*サブパターン(必要ない場合)。メタ文字^および$行の最初と最後に一致します。

パイプgrep "Value1" | grep "Value2"からの質問は、指定したことを行いません-一致しすぎます。例:

 ...、Value1Value2 、、 ... 
 ...、Value1、Value2、... 
 ...、OtherValue1、Value2、... 
 ... 

awkが使用可能な場合(かなり標準的なものです)、次のように実行できます。

$ echo -e 'a,b, c,d\na,val1,val2,c' \
    | awk -F, '$2 == "val1" && $3 == "val2" {++sum} END {print sum}'

awkは、値から空白を自動的に削除します。 ENDは、すべての行が処理された後に一致する特別なパターンです。

1
maxschlepzig

次の関数はBashのみを使用して、必要な処理を実行します。

foo () 
{ 
    local filename="$1";
    while IFS=, read -ra arr; do
        if [[ "${arr[13]}" = "VALUE1" && "${arr[14]}" = "VALUE2" ]]; then
            printf '%s\n' "${arr[13]}" "${arr[14]}";
        fi;
    done < "$filename"
}

使用法: foo [/path/to/file.txt]

サンプル出力:

rany$ cat > source.txt 
a,a,a,a,a,a,a,a,a,a,a,a,a,VALUE1,VALUE2
a,a,a,a,a,a,a,a,a,a,a,a,a,NOMATCH1,NOMATCH2
a,a,a,a,a,a,a,a,a,a,a,a,a,VALUE1,VALUE2

rany$ foo source.txt
VALUE1
VALUE2
VALUE1
VALUE2
0
Rany Albeg Wein