2017-08-15 7 views
1

いくつかの情報を抽出するために、grep(または端末からの他の関数)を解析したいCSVファイルがあります。 彼らは、この形式は以下のとおりである。各ファイルでgrepで得られた各行の末尾に値を追加するには

* Comment 1 
* Comment line 2 explaining what the following numbers mean 
1000000 ; 3208105 ; 0.18 ; 0.45 ; 0.00015 ; 0.1485 ; 0.03 ; 1 ; 1 ; 5 ; 477003 ; 

* Comment 3 
* Comment 4 explaining the meaning of the following lines 

* Comment 5 
0; 706520; p; 30.4983 
1; 20859; p; 57.8 
2; 192814; p; 111.842 
3; 344542; p; 130.543 
4; 54605; p; 131.598 
5; 64746; d; 140.898 
6; 442082; p; 214.11 
7; 546701; p; 249.167 
8; 298394; p; 305.034 
9; 81188; p; 305.034 
....... 

第3のフィールドは、d代わりにpに等しいである最大1つの行が存在し得ます。したがって、dを含む行が存在するか、存在しない行があります。

私はこのようなファイルがたくさんあるので、各ファイルから文字(d)を含む行(存在する場合)を抽出し、この行の後に最初の非コメント行の最後のパラメータを追加して、この例では47703となります。

今まで私は必要な行を別々に抽出することができました。

私が持っているすべてのファイルから dを含むすべての行を抽出することができます。これにより

grep -h -E ' d;' *.csv > output.csv 

そして、これで私は例のようなファイルから正確に数47703を抽出することができます。

grep -v -e "^*" -e " p; " -e " d; " example_file.csv | cut -d \; -f 11 

しかし、私はこれら2つの方法を一緒にする方法がわかりません。

私は冒頭の例から取得したい最終的な出力は次のような一行です:

5; 64746; d; 140.898; 47703 

と私は、現在のディレクトリ内のすべてのCSVファイルに対して、このような行を持っていると思います。

これを行う方法はありますか?

+0

あなたの質問へのサンプル入力用のサンプル入力と、ご希望の出力を追加してください。 – Cyrus

+0

しました。入力は最初の例で出力は最後の行です – jackscorrow

答えて

1

私はループにループのすべての.csvファイルを使用し、各ループの最後に連結された変数のために、grepするから返された値を割り当てるには、エコー:

for f in *.csv ; do value=`grep -v -e "^*" -e " p; " -e " d; " -e '^\s*$' "$f" | cut -d \; -f 11` ; line=`grep -h -E ' d;' "$f" ; echo "$line;$value" ; done

編集:(私も-e '^\s*$'を追加します前に、空白行に一致していました)前に、空白行に一致しました)

これは5; 64746; d; 140.898; 47703のような行だけをエコーし​​ます。上の読みやすさのため

for f in *.csv ; do value=`grep -v -e "^*" -e " p; " -e " d; " -e '^\s*$' "$f" | cut -d \; -f 11` ; line=`grep -h -E ' d;' "$f" ; echo "$line;$value" > output.csv ; done

、同じコード:あなたには、いくつかのファイルにリダイレクトしたい場合は以下のように、その長いコマンドでエコー最後にそれを追加することができ、(見つかったすべての行は、単一の出力ファイルになります)複数行:

for f in *.csv 
do 
    value=`grep -v -e "^*" -e " p; " -e " d; " -e '^\s*$' "$f" | cut -d \; -f 11` 
    line=`grep -h -E ' d;' "$f" 
    echo "$line;$value" 
done 
2

これはsedのための仕事のように聞こえる:

(GNU SED)をparse.sed
/^ +$/d       # Ignore empty lines 
/^[ 0-9;.]+$/h     # Save first "number-only" line to hold space 
/d;/{       # Run block on lines containing ' d; ' 
    G        # Copy saved line to pattern space 
    s/\n.*; ([0-9]+) *; *$/; \1/ # Append the last number on the second line 
    p        # to the first line and print the result 
} 

を解析する。sedの(ポータブルSED)このような

# Ignore empty lines 
/^ +$/d       

# Save first "number-only" line to hold space 
/^[ 0-9;.]+$/h     

# Run block on lines containing ' d; ' 
/d;/{       

    # Copy saved line to pattern space 
    G        

    # Append the last number on the second line 
    # to the first line and print the result 
    s/\n.*; ([0-9]+) *; *$/; \1/ 
    p        
} 

実行それを

sed -Enf parse.sed infile.csv 

出力:これはあなたが唯一の1行で文字グループ[ 0-9;.]を含むを持っていると仮定していること

5; 64746; d; 140.898; 477003 

注意ファイル。

は、次の操作を行い、すべてのローカルのCSVファイルでこれを実行するには:

sed -Enf parse.sed *.csv 
+0

これを1つのファイルに実行しようとすると、 'sed:1:parse.sed:dコマンドの最後に余分な文字があります。 ' – jackscorrow

+0

@jackscorrow :申し訳ありませんが、BSD sedでスクリプトをテストしませんでした。追加された携帯用のバージョン – Thor

+0

を参照してください。これで動作します。ありがとう!できるだけ早く私はあなたの解決策を試し、どちらが良いかを見てみましょう – jackscorrow

関連する問題