Shell

如何測試具有值的文件?

  • November 23, 2014

我在用

source ~/.rvm/scripts/rvm
repos="repo_1_ruby_193 repo_2_ruby_211 repo_3_ruby_191"
> rvm_check.txt
for repo in $repos
do
 cd ~/zipcar/$repo 2>rvm_check.txt
 cd ..
 echo $repo
 if [ -z `cat rvm_check.txt | grep not` ] # line 9
   then
     echo "YES"
   else
     echo "NO"
     exit 1
 fi  
done

它大部分都在工作,但我得到:

$ ./multi_repo_rubies.sh 
repo_1_ruby_193
YES
repo_2_ruby_211
YES
repo_3_ruby_191
./multi_repo_rubies.sh: line 9: [: too many arguments
NO
$

無論我嘗試-s還是-z

我得到了我想要的是/否,但如何避免[:錯誤?

代替:

if [ -z `cat rvm_check.txt | grep not` ]

和:

if ! grep -q not rvm_check.txt

test在語句中使用的原因if是因為它設置了一個退出程式碼,shell 使用該程式碼來決定轉到thenorelse子句。 grep還設置退出程式碼。因此,這裡不需要測試 , [grep如果找到字元串,則將退出程式碼設置為成功 (0)。如果找不到字元串,您希望成功。因此,我們通過使用來否定退出程式碼結果!

解釋

測試命令 ,[期望後面跟著一個字元串-z。如果 grep 命令產生多個單詞,那麼測試將失敗並出現您看到的錯誤。

例如,考慮這個範例文件:

$ cat rvm_check.txt
one not two

的輸出grep看起來像:

$ cat rvm_check.txt | grep not
one not two

test執行時,所有三個單詞都出現在[...]導致命令失敗的內部:

$ [ -z `cat rvm_check.txt | grep not` ]
bash: [: too many arguments

這與您輸入的內容相同:

$ [ -z one not two ]
bash: [: too many arguments

一種解決方案是使用雙引號:

$ [ -z "`cat rvm_check.txt | grep not`" ]

雙引號可防止 shell 執行分詞。因此,grep此處的輸出被視為單個字元串,而不是拆分為單獨的單詞。

但是,由於grep設置了一個合理的退出程式碼,所以如上面推薦的行所示,不需要測試。

補充評論

  • 目前首選的命令替換形式是$(...). 雖然反引號仍然有效,但它們很脆弱。特別是,反引號不能嵌套。
  • 在命令上採用文件名的命令上,cat不需要使用 。代替:
cat somefile | grep something

只需使用:

grep something somefile

引用自:https://unix.stackexchange.com/questions/169469