2016-02-04 42 views
0

我在Stack Overflow上搜索了幾個問題和答案,但是它們都不適用於我的情況,我不知道爲什麼我的正則表達式不起作用。如果你能指出我錯誤的想法,我會非常感激。從一行中找到確切的單詞並用grep/sed刪除那一行

測試用例:文本文件包含

AllenZhou:9175186661:111th 1111 NY, 11111 
XiaoyuZhou:9175186662:2222 222th 22222 NY 22222 
Allen:1231231234:abc rd, PA 

這裏是我的功能:

checkEntry(){ 
    vaildName=true 
    while read entry 
    do 
      if $(echo $entry | grep --quiet $name)//$name read from keyboard 
      then 
        vaildName=false 
      fi 
    done < $fileName 
} 

如果我進入Zhou,我的函數將返回兩個AllenZhou,並XiaoyuZhou。我做了小的研究之後,我改變了grep命令參數

if $(echo $entry | grep --quiet ^$name:$) 

事實證明,它從來沒有發現任何東西AllenZhouXiaoyuZhou –我很困惑。

sed -i -n /$name/d $fileName 

這是我用來刪除包含字符串模式的行的代碼。問題和grep一樣,如果我輸入ZhouAllen,該命令將刪除包含關鍵字的兩行。但是,當我改變

sed -i -n /\<$name\>/d $fileName 

它不會刪除AllenZhouXiaoyuZhouZhou ...我再一次感到困惑。

+0

根據您的樣本輸入(編輯您的Q),請顯示您的預期輸出。並指明哪個搜索目標。也許你將不得不使用'sed'/ AllenZhou/d''。謝謝,祝你好運。 – shellter

+0

'sed -i -n/pattern/d'將會刪除你的文件 - 可能不是你想要的! –

+1

谷歌外殼的引用慣例很快,因爲你需要引用你的變量默認情況下,如果你有一個特定的目的,這樣做,並完全理解所有的影響,只留下他們不加引號。如果你不開始引用你的變量,你很快會看到一些奇怪的,危險的影響。 –

回答

2

if中使用命令替換不符合您的想法。您正在捕獲grep的輸出 - 其中-q選項始終爲空字符串 - 並且作爲參數傳遞給if,該參數需要命令名或管道作爲其參數。它基本上試圖執行空字符串,這當然不會做任何有用的事情(最終效果是if條件將總是成功)。

你想簡單地

if echo "$entry" | grep -q "$name"; then 
    : stuff 
fi 

以上慣用和高效

if [[ "$entry" = *"$name"* ]]; then 
    : stuff 
fi 

甚至

case $entry in *"$name"*) 
    : stuff;; 
esac 

(雙括號[[ ... ]]都是Bash而已,而case可以移植到任何POSIX shell,甚至連原來的Bourne shell。單方括號也是便攜式的,他們可以做... 東西這樣,但它比你想要的更醜,更脆,更復雜。)

還要注意報價。包含任意字符串的變量needs to be quoted

另一方面,您希望使用read -r - 如果沒有選項,read的行爲會帶來一些令人討厭的遺留行爲,以便在某些特定情況下實現歷史向後兼容性。

但是,分別檢查每條線只是麻煩。整個功能可能是

grep -q "$name" "$fileName" 

它也返回實際結果;你的函數沒有做到的事情(除了設置一個全局變量,如果這就是它的作用 - 很難從上下文中看出來。即使在shell腳本中,在函數中使用全局變量也是一個壞主意)。

也許你會想要一些正則表達式錨定來限制匹配到第一個字段。 grep "^[^:]*$name"在第一個冒號前的任何地方尋找匹配。

數據中沒有詞語邊界(空格,標點符號等),只是大小寫的變化,所以\<\>無法匹配這些名稱。觀察你的大小寫模式,也許你想在比賽結束後要求大寫字母或冒號; "^[^:]*$name[[:upper:]:]"

如果最終目標是提取地址或電話號碼,那就直接做。你需要Awk而不是grep

awk -F : -v name="$name" 'BEGIN { pat = name "($|[[:upper:]])"; result = 1 } 
    $1 ~ pat (print $2; result = 0 } 
    END { exit result }' "$fileName" 

awk的腳本打印第二場從任何匹配線集的結果代碼,這樣就可以在一個或if條件while使用它。

相關問題