2015-09-03 24 views
0

我幾乎是全新的編碼,我很感激反饋。我正在嘗試製作一個shell腳本,用於評估文本文件中的信息,並在滿足特定條件時移動所述文本文件。我的代碼如下:awk,bin/sh 0:1:找不到

#!/bin/bash 

stock=HD 

awk ' /Rank/ { 
    if ($4 == "1-Strong") system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/1/"'$stock'.txt") ; 
    else if ($4 == "2-Buy") system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/2/"'$stock'.txt") ; 
    else if ($4 == "3-Hold") system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/3/"'$stock'.txt") ; 
    else if ($4 == "4-Sell") system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/4/"'$stock'.txt") ; 
    else if ($4 == "5-Strong") system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/5/"'$stock'.txt") 
} ' $stock.txt 

當我嘗試運行該腳本,我得到這個錯誤:

[email protected]:~/Desktop/Stocks$ ./stockscript7.sh 
/bin/sh: 1: 0: not found 

我確信我是在bash shell中。我確實使用chmod來賦予腳本權限。否則,從這個錯誤信息,我迷失在接下來的嘗試。任何幫助將非常感激。

+0

你試過使用'#!/ usr/bin/env bash'嗎?也許bash不在你認爲的地方。使用這種形式的she-bang線是便攜式的,適用於所有* nix系統。然而'#!/ bin/bash'不是。當你從終端使用bash時,你是否使用'sh'或'bash'?你使用哪一種是有區別的。 – rbaleksandar

+0

如果你用很小的代碼編寫代碼,並且測試每個修改,而不是編寫完整的腳本,然後嘗試對其進行故障排除,則會發現編碼更容易。 –

+2

Eww。以這種方式使用'system()'會給你帶來嚴重的安全漏洞。 –

回答

3

以下是翻譯本地慶典,與沒有使用awk濫用作爲你相關的bug(考慮會發生什麼,名爲EVIL'$(rm -rf .)'.txt輸入文件 - 與命令touch $'EVIL\'$(rm -rf .)\'.txt'創建):

#!/bin/bash 

stock=HD 

while IFS= read -r line; do 
    [[ $line = *Rank* ]] || continue 
    read -r _ _ _ rank _ <<<"$line" 
    case $rank in 
    1-Strong) mv -- "$stock.txt" ~/Desktop/Stocks/1/ ;; 
    2-Buy) mv -- "$stock.txt" ~/Desktop/Stocks/2/ ;; 
    3-Hold) mv -- "$stock.txt" ~/Desktop/Stocks/3/ ;; 
    4-Sell) mv -- "$stock.txt" ~/Desktop/Stocks/4/ ;; 
    5-Strong) mv -- "$stock.txt" ~/Desktop/Stocks/5/ ;; 
    esac 
done <"$stock.txt" 

然而,這並沒有使,因爲它是書面多大意義:你每跑匹配Rank文件相符的一個mv - 但你不能成功移動單個文件超過一次。也許你只是想讀第第一行行包含Rank,並根據第四列破折號前面的數字重命名該文件?

#!/bin/bash 
stock=HD 
if read -r _ _ _ rating _ < <(grep -e Rank "$stock.txt") && [[ $rating ]]; then 
    mv -- "$stock.txt" ~/Desktop/Stocks/"${rating%%-*}"/ 
fi 

說明:

  • <(...)被替換爲一個文件名,其,讀出時,返回所包圍的命令的輸出。因此,foo < <(...)在父shell中運行foo,其標準輸入來自...中的命令。請參閱BashFAQ #24以瞭解爲什麼這是必需的,而不是運行grep -e Rank "$stock.txt" | read _ _ _ rating _
  • read _ _ _ rating _將其輸入流的第四個字讀入變量rating。 (第一,第二,第三和第五等)讀入名爲_的變量中,這是您不關心/想要丟棄的東西的約定)。
  • "${rating%%-*}"扔掉在變量rating以下第一-所有內容,從而轉換到1-Strong12-Buy2

然而,所有上述不解釋確切的錯誤你正在接受。爲了得到,讓我們打破你的awk命令:

system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/1/"'$stock'.txt") ; 

...所以,什麼是字符串連接在一起,並傳遞給system()(因此/bin/sh)?

system(
    "mv " 
    "'$stock'.txt" 
    " " 
    ~/Desktop/Stocks/1/"'$stock'.txt" 
) ; 

看到問題在這裏?第四部分(您打算將其與其他部分連接在一起)不是awk中的字符串!因此,如果它包含/操作,那麼這些操作將被視爲數字分區 - 將內容之前的內容轉換爲數值,然後除以內容之後的內容(同樣轉換爲整數)。在包括我在內的一些awk版本中,這會導致零除錯誤;你的顯然不同。

(另外,$stock文字字符串,而不是與HD這裏取代,但這是另外一個問題)

0

你正在使事情變得過於複雜:1)僅僅使用awk,2)在這些mv命令的目標路徑中重複文件名。

我會假定「Rank」行有空格分隔的列,並且第四個是包含您的id的列,就像您自己所假設的一樣。 如果這個或下面的假設不成立,這裏的解決方案可能會給您帶來問題。查看Charle的答案。

如果確定第四場總是包含與模式digits-text一個字符串,那麼你就可以

#!/bin/bash 

stock=HD 

id=`cat "$stock.txt"|grep Rank| cut -d ' ' -f 4| sed '[email protected]*@@g'` 
echo "$stock.txt" ~/Desktop/Stocks/"$id" 
#mv "$stock.txt" ~/Desktop/Stocks/"$id" 

我註釋掉實際mv命令試試。回聲線將允許您仔細檢查文件是否確實會到達正確的目的地。進行一些測試,如果事情看起來沒問題,通過刪除#標誌取消對mv行的註釋。

編輯:一定要確保所有的目錄〜/桌面/股票/ $ ID存在發出mv命令之前。否則你會失去這些文件!,因爲他們會相互覆蓋,只有最後一個文件的內容移動到任何給定的〜/ Desktop/Stocks/$ id目錄才能存活 - 但命名爲$ id!

下面的代碼將確保它們被移動到一個目錄中,並且不會相互覆蓋。

#!/bin/bash 

stock=HD 
DDIR=~/Desktop/Stocks 

id=`cat "$stock.txt"|grep Rank| cut -d ' ' -f 4| sed '[email protected]*@@g'` 
echo "$stock.txt" ~/Desktop/Stocks/"$id" 
{ [ -d "$DDIR/$id" ] || mkdir "$DDIR/$id" ;} && mv "$stock.txt" ~/Desktop/Stocks/"$id" 

這首先檢查文件夾$ DDIR/$ id是否存在,如果不存在則進行檢查。只有這樣才能進行實際的移動。

+0

貓的無用用途。 – Jens

+0

由於缺少引號也是很糟糕的錯誤。如果正在處理的股票名稱中包含空格或水平字符,或者(由於某種原因)'id'字段具有相同的內容? –

+0

順便說一句,在'$ id'後加上最後的'/'可以確保它是一個用作目的地的目錄,並且避免了你擔心的文件覆蓋情況。雖然你*還*需要更多的引號來確保'mv'只傳遞你期望的參數個數。 –

2

您正在創建此執行樹:

shell { awk { system(shell) } } 

不要做這是非常混亂和容易出錯的。代之以(或者同樣簡單):

shell { awk } 

例如這可能是所有你需要的(取決於HD.txt的內容):

mv "${stock}.txt" ~/Desktop/Stocks/"$(awk '/Rank/{ sub(/-.*/,"",$4); print $4 }' "${stock}.txt")" 
+0

我建議引用你在調用awk的'$()'擴展 - 如果僅僅是偏執狂 - 但這是一個我沒有想到的好方法。 (當然,你也希望*不*引用'〜',或者如果引用整個參數來替換它'$ HOME') –

+0

老實說,我只是把它扔在那裏給OP是一種可能性的想法。他可能真的需要一些不同的東西,但是直到我們看到他的輸入文件內容,我們才肯定知道。我會加上引號,謝謝。 –