2015-06-01 37 views
0

我有一個bash腳本,它遍歷鏈接列表,每個鏈接都有一個html頁面,greps爲特定的字符串格式(語法爲:CVE-# ### - ####),刪除周圍的html標籤(這是一個一致的格式,不需要特殊的處理),在變更日誌文件中搜索結果字符串ID,最後根據字符串ID是否爲發現與否。bash腳本grep使用變量無法找到實際存在的結果

找到的字符串ID被設置爲一個變量。問題是,當變量grep沒有結果,即使我肯定知道應該有一些ID的。下面是腳本的相關部分:

for link in $(cat links.txt); do 
    curl -s "$link" | grep 'CVE-' | sed 's/<[^>]*>//g' | while read cve; do 
     echo "$cve" 
     grep "$cve" ./changelog.txt 
    done 
done 

如果我硬編碼在grep命令已知ID,腳本發現ID和預期回報的事情。我已經嘗試了許多變量對這個變量進行grepping(例如導出它並執行命令擴展,將變更日誌和管道連接到grep,通過curl鏈的命令擴展直接設置變量,圍繞變量的單引號和雙引號,半個打其他的東西)。

我錯過了從curl | grep | sed鏈輸出的變量細微的東西嗎?當它被stdout或>>回顯到一個文件時,事情看起來很好(單個ID沒有奇數字符或回車等)。

任何提示或替代解決方案將不勝感激。謝謝!

FYI:

OSX:$bash --version 
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin14) 

編輯:

,我是curl'ing HTML文件是充滿了回車的。使用set -x運行腳本很有幫助,因爲它顯示了真正的字符串被grepped:$'CVE-2011-2716 \ r'。

+ read -r link 
+ curl -s http://localhost:8080/link1.html 
+ sed -n '/CVE-/s/<[^>]*>//gp' 
+ read -r cve 
+ grep -q -F $'CVE-2011-2716\r' ./kernelChangelog.txt 

也從另一個角度考察,在vim打開文件捲曲顯示^ M和做一個printf%的 「$ CVE」 | xxd還顯示回車符十六進制代碼0d附加到grep'd變量。依靠'echo'標準輸出是診斷事物的錯誤方式。用一個有效的CVE編寫一個簡單的html頁面 - #### - ####,但是然後添加一個回車符(在vim插入模式下,只需鍵入ctrl-v ctrl-m來插入回車符)將創建一個示例文件與上面的原始腳本片斷一起失敗。

這是非常標準的字符串消毒的東西,我應該想通了。解決方案是刪除回車,管道到tr -d'\ r'是這樣做的一種方法。我不知道有這一系列的步驟上SO特定的重複,但在任何情況下,這是我現在的工作腳本了:

while read -r link; do 
    curl -s "$link" | sed -n '/CVE-/s/<[^>]*>//gp' | tr -d '\r' | while read -r cve; do 
    if grep -q -F "$cve" ./changelog.txt; then 
     echo "FOUND: $cve"; 
    else 
     echo "NOT FOUND: $cve"; 
    fi; 
    done 
done < links.txt 
+1

不信任'echo'。 *尤其是*帶有不加引號的參數。 'printf'[%s] \ n'「$ cve」'和'printf%s'$ cve「 xxd'。 –

+0

我會解決這個問題時,排除故障,並開始通過使用卷管理單鏈接管道grep和測試標準輸出來找出真正的問題是什麼。 – cchamberlain

+1

您可能還想發佈可複製問題的示例數據。 –

回答

2

HTML文件可以在行尾包含回車符,您需要將其過濾掉。

curl -s "$link" | sed -n '/CVE-/s/<[^>]*>//gp' | tr -d '\r' | while read cve; do 

請注意,有沒有必要使用grep,你可以在sed命令使用正則表達式過濾器。(您也可以使用sed中的tr命令刪除字符,但對\r這樣做很麻煩,所以我改爲將其傳送到tr)。

+0

好抓! ... – hek2mgl

2

它應該是這樣的:

# First: Care about quoting your variables! 

# Use read to read the file line by line 
while read -r link ; do 
    # No grep required. sed can do that. 
    curl -s "$link" | sed -n '/CVE-/s/<[^>]*>//gp' | while read -r cve; do 
     echo "$cve" 
     # grep -F searches for fixed strings instead of patterns 
     grep -F "$cve" ./changelog.txt 
    done 
done < links.txt 
+0

感謝您清理東西,但事情仍然無法正常工作。該$ cve變量必須有錯誤。我會深入挖掘。 – mcanfield

+0

我需要看到'links.txt'和'changelog.txt'的內容。 – hek2mgl

+0

@Barmar給我提示在腳本中使用set -x。這表明有一個回車\ r被追加到$ cve變量。我會給他一個機會發布解釋爲什麼和/或如何解決的實際答案。如果他不這樣做,也許你可以編輯這個當前的答案,包括這一點,我會將其標記爲接受。無論如何,謝謝你的清理。 – mcanfield