2017-08-07 29 views
0

這是我想出了慶典元運算符預期的錯誤

#!/bin/bash 

expression=$1 
field=$2 
if [ -z "$expression" ]; then 
echo "expression is missing" 
exit 1 
fi 

if [ -f /home/miked/table ]; then 
    if [ -f table ] && [ grep "$expression table" ]; then 
    grep "$expression" table | cut -d: -f${2:-3} | clipit 
    else 
    echo "no match found" 
    fi 
else 
    echo "there is no table file" 
fi 

由於事實上,我知道如何解決它的劇本,但我不知道爲什麼 它的固定。

如果我刪除grep"之間的空間,一切工作正常,我似乎無法理解爲什麼。

如果我直接在命令行上執行grep something file,它工作良好。爲什麼要在腳本中將grep粘貼到"

+0

不,如果你做的工作'[\'$ grep的表情表\']'? – TallChuck

+0

是的,但我需要在這裏解釋 – jaindoe

+0

附註,與問題無關:爲什麼你首先檢查'/ home/miked/table'是否存在,但是你在當前目錄中使用'table'? –

回答

2

你並不需要包裝內方grep電話括號。 [test命令的別名(但通常情況下,大多數shell會使用內置命令複製該命令)。您可以使用man test查看該命令的語法。你想要做的是檢查,如果在一些文件中存在$expression table,所以不是你需要把它寫成:

#!/bin/bash 

expression="$1" 
field="$2" 
if [ -z "$expression" ]; then 
    echo "expression is missing" 
    exit 1 
fi 

if [ -f /home/miked/table ]; then 
    if [ -f table ] && grep "$expression table"; then 
    grep "$expression" table | cut -d: -f${2:-3} | clipit 
    else 
    echo "no match found" 
    fi 
else 
    echo "there is no table file" 
fi 

但是還有更多的問題,你的腳本。

  1. 您打印錯誤stdout,而不是stderr這使得他們看不到管道時,你的腳本其他工具的輸出,而不是你應該使用echo "error" >&2,最好使用單獨的函數,該函數。
  2. 您只傳遞一個參數給grep,我認爲應該有2:grep "$expression" table
  3. 你的第一個grep電話也打印到stdout,我相信你想超過那個,所以改爲使用-q標誌。
  4. 這是好主意,讓「上的錯誤退出」使用set -e和使用set -o pipefail
  5. 你不使用外部文件「關於管道錯誤退出」,所以你可以刪除檢查了點。
  6. 你不使用你的$field變量。
  7. 使用警衛clausules而不是if s進行致命的錯誤檢查,因爲它會更容易重構您的腳本。

所以整個文件可以寫成:

#!/bin/bash 

set -eo pipefail 

perror() { 
    echo "$1" >&2 && exit 1 
} 

expression=$1 
field=${2:-3} 
file=${3:table} 

[ -z "$expression" ] || perror "expression is missing" 
[ -f "$file" ] || perror "there is no '$file' file" 

grep "$expression" "$file" | cut -d: -f"${field}" | clipit || perror "no match found" 
+0

'grep「$ expression table」'在你的第一個例子中不起作用,grep需要兩個參數。不過,您稍後會指出這一點。 –

+0

@BenjaminW。第一個腳本只是修復了作者錯誤。第二部分是關於這個腳本的所有其他問題,還提到了這個問題(因爲我們不能100%確定OP意圖是什麼)。 – Hauleth

+1

夠公平的。注意'set -e'帶有很多缺陷:http://mywiki.wooledge.org/BashFAQ/105 –

0

這裏根本不需要[ ]。你對grep的退出狀態感興趣,它已經給你一個了;壓制它的輸出,你可以使用-q選項:

if [ -f table ] && grep -q "$expression" table; then 

文件名不應該是引號內,無論是。

如果使用[ ]未經任何測試,則默認爲-n:「如果字符串不爲空,則爲true」。這個測試需要一個參數,這就是爲什麼如果你刪除空間它似乎爲你工作:它只是檢查字符串grep$expression table擴展爲非零,並且它總是。

+0

爲什麼grep「表達式」結果有兩個參數?我認爲如果它有一個然後grep退出狀態將是0這是好的,如果沒有多少它會產生退出狀態1,這將我帶到其他子句,爲什麼這行產生2個參數? – jaindoe

+0

這是'[]'的兩個參數:第一個是'grep',第二個是''表達式表''。 –

0

有可以做,以解決這一問題相當多的事情,你的問題主要是以下行: if [ -f table ] && [ grep "$expression table" ]; then

如果「表」存在你已經測試過,所以你做一遍一旦成功,表示[ grep "$expression table" ]正在評估,這是分解爲'[' grep 'expression table' ']'這意味着什麼都沒有。

你應該改用$()並評估出現次數,或者像本傑明提到的那樣,如果這就是你想要的,可以完全跳過它。

我想我們怎麼還使用測試表明這樣的事情

#!/bin/bash 
expression=$1 
field=$2 
table_file=/home/miked/table 
if [ -z "$expression" ]; then 
    echo "expression is missing" 
    exit 1 
fi 

if [ -f $table_file ]; then 
    if [ $(grep -q "$expression $table_file") -gt 0 ]; then 
     grep "$expression" $table_file | cut -d: -f${2:-3} | clipit 
    else 
     echo "no match found" 
    fi 
else 
    echo "there is no table file" 
fi 

注意,這可能是凝結成:

#!/bin/bash 
expression=$1 
field=$2 
table_file=/home/miked/table 
if [ -z "$expression" ]; then 
    echo "expression is missing" 
    exit 1 
fi 

if [ -f $table_file ]; then 
    grep -q $expression $table_file && grep "$expression" $table_file | cut -d: -f${2:-3} | clipit || echo "no match found" 
else 
    echo "there is no table file" 
fi 
+0

這真是'grep -q'的主要用例。 –

+0

你說得對,我完全忽略了它 –