2017-08-15 150 views
1

我有一些CSV文件,我想用grep解析(或從終端獲取其他函數)以提取一些信息。 他們以這種形式:如何在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 
....... 

在每個文件中可能有至多一個線,其中第三場等於d而不是p。所以要麼有一行包含d或者沒有。

我有很多像這樣的文件,我想要做的是從每個文件中提取包含字母d的行(如果存在),並在此行後追加第一個非註釋行的最後一個參數,在這個例子中是47703

到目前爲止,我設法分開提取我需要的線。

有了這個我可以提取從每一個文件I具有包含d每一行:

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

而與此我可以從像在例的文件中提取準確數量47703

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

但我不知道如何把這兩個放在一起。

最終的輸出,我想從一開始的例子來獲得是這樣的一行:

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*$'首先grep,得到與第一個沒有評論線上的值線,之前,它匹配空行)

這隻能迴應像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工作:

parse.sed(GNU 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 

輸出:

5; 64746; d; 140.898; 477003 

注意,這裏假設你只有包含字符組[ 0-9;.]在一行文件。

要在所有本地CSV文件,運行此執行以下操作:

sed -Enf parse.sed *.csv 
+0

當我嘗試運行它到一個文件時,它給了我錯誤'sed:1:parse.sed:在d命令結尾的額外字符' – jackscorrow

+0

@jackscorrow :對不起,我沒有在BSD sed中測試腳本。看到增加的便攜式版本 – Thor

+0

好吧,現在它工作。謝謝!只要我可以,我會嘗試你的解決方案,看看哪一個更好 – jackscorrow

相關問題