2017-05-08 239 views
0

我有一个脚本,用于搜索注释中包含“TODO” 注释的源文件。此外,我使用grep,git blame,uniqsort的级联以得到 由编写TODO评论的人排序的列表。不同的shell行为:bash忽略换行符,zsh保留它

下在bash和zsh的优秀作品:

#!/bin/bash 

for FILE in $(grep -r -i "todo" apps/business | awk '{print $1}' | sed 's/://' | sed 's/\#//') 
do 
git blame $FILE | grep -i "todo" 
done | sort -k2 | uniq 

现在我想指望所有条目。不要再次拨打(费时) grep/git blame,我想将所有内容保存到$MATCHES,以便将其计数为 ,而无需再次对其进行评估。

MATCHES=$(for FILE in $(grep -r -i "todo" apps/business | awk '{print $1}' | sed 's/://' | sed 's/\#//') 
do 
    git blame $FILE | grep -i "todo" 
done | sort -k2 | uniq) 

echo $MATCHES 

这就是我的经验在bash/zsh,使用不同的行为:

的zsh:返回相同的第一个脚本(如预期)

庆典:忽略的git的新行责备,把一切都放在一条线上。 wc -l占1行。

我在这里错过了什么?为什么bash在这里的行为不同? 如何让bash不要忽略换行符?

+1

尝试'echo“$ MATCHES”'。如果没有引号,bash会根据IFS的值将这个变量解析为单词。 – ccarton

回答

2

zsh默认情况下不对未加引号的参数扩展$MATCH执行分词。使用echo "$MATCHES" | wc -lbash也应该可以。

注意这是迭代命令输出的错误方法;改为使用while循环和read命令。

grep -ri "todo" apps/business | awk '{print $1}' | sed -e 's/://' -e 's/\#//' | 
    while IFS= read -r FILE; do 
    git blame "$FILE" | grep -i todo 
    done | sort -k2 | uniq 
+0

谢谢,这个工作得很好。 – pentix

+0

您能否简单解释为什么'for'是错误的方式,while''while'read'更好?谢谢! – pentix

+1

参见[Bash FAQ 001](http://mywiki.wooledge.org/BashFAQ/001) – chepner