2011-04-27 164 views
1

我有一個由數字組成的文件。通常,每行包含一個單一的數字。我想要統計文件中以數字「0」開頭的行數。如果是這樣的話,那麼我想做一些後期處理。將命令的輸出分配給shell變量並獲取變量大小

雖然我能夠正確檢索相應的行號,但檢索行的總數不正確。下面,我發佈我正在使用的代碼。

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile}); 
# linesToRemove=$(grep -n "^0" ${inputFile} | cut -d":" -f1); 

linesNr=${#linesToRemove} # <- here, the error 
# linesNr=${#linesToRemove[@]} # <- here, the error 

if [ "${linesNr}" -gt "0" ]; then 
    # do something here, e.g. remove corresponding lines. 
    awk -v n=$linesToRemove 'NR == n {next} {print}' ${anotherFile} > ${outputFile} 
fi 

另外,至於基於awk的命令,我怎樣才能使用shell變量?我嘗試了下面的命令,但它不能正常工作,因爲'myIndex'被解釋爲文本而不是變量。

linesToRemove=$(awk -v myIndex="$myIndex" '/^myIndex/ { print NR;}' ${inputFile}); 

考慮開始與${inputFile}發現0行號,我想從${anotherFile}刪除相應的行號。兩個$ {INPUTFILE} $ {anotherFile}下面給出一個例子,:

// ${inputFile} 
0 
1 
3 
0 

// ${anotherFile} 
2.617300e+01 5.886700e+01 -1.894697e-01 1.251225e+02 
5.707397e+01 2.214040e+02 8.607959e-02 1.229114e+02 
1.725900e+01 1.734360e+02 -1.298053e-01 1.250318e+02 
2.177940e+01 1.249531e+02 1.538853e-01 1.527150e+02 

// ${outputFile} 
5.707397e+01 2.214040e+02 8.607959e-02 1.229114e+02 
1.725900e+01 1.734360e+02 -1.298053e-01 1.250318e+02 

在上面的例子中,我需要刪除線0和從${anotherFile}3,因爲這些行對應於開頭的行0 in ${inputFile}

回答

1

,那麼這行是錯誤的。

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});

上述表示打印行數時行從0開始,你的linesToRemove變量將包含所有的行號,而不是行的總數。使用END{}塊來捕獲總數。例如

linesToRemove=$(awk '/^0/ {c++}END{print c}' ${inputFile});

至於使用awk的內部變量您的第二個問題,使用正則表達式運算符~。然後設置你的myIndex變量包括^

linesToRemove=$(awk -v myIndex="^$myIndex" '$0 ~ myIndex{ print NR;}' ${inputFile});

最後,如果你只是想刪除那些以0開頭的行,那麼就乾脆刪除它

awk '/^0/{next}{print $0>FILENAME}' file 

如果你想使用輸入文件中捕獲的內容從另一個文件中刪除行,這裏有一種方法

paste -d"|" inputfile anotherfile | awk '!/^0/{gsub(/^.*\|/,"");print}' 

或者只是一個awk命令

awk 'FNR==NR && /^0/{a[FNR]} NR>FNR && (!(FNR in a))' inputfile anotherfile 

粗解釋:FNR == NR & &/^ 0 /裝置處理的第一個文件整個行開頭0,並把它的行號到數組aNR>FNR表示處理下一個文件,如果行號不在數組中,則打印該行。請參閱gawk文檔瞭解FNR,NR等的含義

+0

@ ghosdog74,謝謝!實際上,最終目標是從一個文件中檢索以0開頭的行,然後從另一個文件中刪除相應的行。此外,是否有可能使用變量'linesToRemove'的大小/長度來查找總行數? – Javier 2011-04-27 12:38:10

+0

@Javier,你應該發佈這些文件的樣本,並顯示你的最終輸出。我可以更好地向你展示,如果不是比你現在正在做的更有效的方式 – ghostdog74 2011-04-27 12:45:58

+0

@ ghosdog74,我更新了這篇文章,幷包含了這兩個文件的一些示例。 – Javier 2011-04-27 12:56:32

0

一般來說,如果你這樣做:

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile}); 

,而不是這樣的:

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile}); 
linesNr=${#linesToRemove} 

使用本:

linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile}); 
linesNr=${echo $linesToRemove|awk '{print NF}'} 

POC:

cat temp.sh 
#!/usr/bin/ksh 

lines=$(awk '/^d/{print NR}' script.sh) 
nooflines=$(echo $lines|awk '{print NF}') 
echo $nooflines 
torinoco!DBL:/oo_dgfqausr/test/dfqwrk12/vijay> temp.sh 
8 
torinoco!DBL:/oo_dgfqausr/test/dfqwrk12/vijay> 
+0

「換行換行標籤」?並非如此。如果你不能「引用」這個變量,那麼你的變量會受到shell分詞(http://wiki.bash-hackers.org/syntax/expansion/wordsplit) – 2011-04-27 11:12:54

+0

哦,你是正確的刪除它。 – Vijay 2011-04-27 11:46:04

1

我認爲你必須做到以下幾點指定數組:

linesToRemove=($(awk '/^0/ { print NR; }' ${inputFile})) 

而獲得的元素數量做(因爲你有一個註釋行):

linesNr=${#linesToRemove[@]} 

要刪除行從該文件,你可以這樣做:如果你想數以0開頭的文件中的行數

sedCmd="" 
for lineNr in ${linesToRemove[@]}; do 
    sedCmd="$sedCmd;${lineNr}d" 
done 
sed "$sedCmd" ${anotherFile} > ${outputFile} 
+0

謝謝!通過在'linesToRemove'數組中以'0'開始的行號,我怎樣才能用它從文件中刪除這些行號? – Javier 2011-04-27 12:25:23

+0

@Javier:我使用'd'(delete)命令爲'sed'命令添加了一個示例。 – bmk 2011-04-27 13:24:36

+0

謝謝!有沒有辦法加快代碼?我有幾個文件需要處理,並且執行上面的代碼只有一個文件需要一些時間。 – Javier 2011-04-27 13:51:49

0

它很大程度上取決於您正在進行的後處理,但是您是否真的需要實際計數?爲什麼不這樣做:

 
if grep ^0 $inputfile > /dev/null; then 
    # There is at least one line with a leading 0 
    : 
fi 

grep -v ^0 $inputfile | process-lines-without-leading-zero 
grep ^0 $inputfile | process-lines-with-leading-zero 

或者,哪怕只是:

 
if grep ^0 $inputfile | process-lines-with-leading-zero; then 
    # some post processing 
    : 
fi 

- 編輯 -

根據你已經在您的評論說,我會建議不同的方法。如果我理解正確,您想讀取文件a,查找表格^ 0 [0-9] *, 的行,然後從文件b中刪除這些行號。如果文件變大,一次只做一行很慢。只要這樣做:

 
cmd=$(grep '^0[0-9]*$' a | sed 's/$/d;/g') 
sed "$cmd" b 

對cmd的賦值形成一個sed命令來刪除這些行。在b上調用sed將省略這些行。您需要適當地重定向sed輸出(也許是臨時文件,然後回到b,或者如果您使用的是gnu sed,只需使用'sed -i')。

+0

謝謝!實際上,我需要做的是首先找到文件「A」中以'0'開頭的行,然後從文件'B'中刪除這些行。我更新了原始文章並插入了用於刪除檢索到的行的命令。 – Javier 2011-04-27 12:36:46

+0

@javier。如果沒有行匹配,則cmd爲空,最終的sed爲空操作,並且b將保持不變。 – 2011-04-27 13:38:11

+0

我調用了'cmd = $(grep'^ 0 [0-9] * $'$ {inputFile}'後,得到以下消息:'sed:-e expression#1,char 2: | sed's/$/d;/g')'然後是'sed'$ cmd「$ {anotherFile}' – Javier 2011-04-27 13:39:18

0

由於大量的編輯這個問題,似乎最容易開始一個新的答案。你的問題可以用一個簡單的單行來解決:

 
$ sed "$(grep -n ^0 $inputFile | sed 's/:.*/d;/g')" $anotherFile > $outputFile 
相關問題