计算grep结果不会在bash脚本中工作

时间:2016-07-30 13:05:24

标签: linux bash shell grep

我的问题不容易提出,我尝试用以下示例解释问题:

/home/luther/tipical_surnames.txt

Smith
Johnson
Williams
Jones
Brown
#Davis
Miller
Wilson
#Moore
Taylor
Anderson

/home/luther/employers.txt

2000    Johnson     A lot-of details / BJC3000,6000, i550                0
2101    Smith       A lot-of details / BJC3000,6000, i550                0
2102    Smith       A lot-of details / BJC3000,6000, i550                0
2103    Jones       A lot-of details / BJC3000,6000, i550                0
2104    Johnson     A lot-of details / BJC3000,6000, i550                0
2100    Smith       A lot-of details / BJC3000,6000, i550                0

我有一个最喜欢的姓氏列表和另一个雇主姓名的列表。 让我们使用控制台检查公司中有多少人拥有最受欢迎的姓氏:

grep -v "#" /home/luther/tipical_surnames.txt | sed -n 1'p' | cut -f 1
Smith
grep Smith /home/luther/employers.txt | wc -l
230

工作完美。 现在让我们使用简单的bash脚本检查前5个最受欢迎的姓氏:

#!/bin/bash
counter=1
while [ $counter -le 5 ]
 do
  surname=`grep -v "#" /home/luther/tipical_surnames.txt | sed -n "$counter"'p' | cut -f 1`
  qty=`grep "$surname" /home/luther/employers.txt | wc -l`
  echo $surname
  echo $qty
  counter=$(( $counter + 1 ))
 done

结果如下:

Smith
0
Johnson
0
Williams
0
Jones
0
Brown
0

怎么了?

更新 就像我写的那样,我在其他计算机上测试了脚本,一切正常。 在我尝试以下后:

root@problematic:/var/www# cat testfile.bash
#!/bin/bash
for (( c=1; c<=5; c++ ))
{
echo $c
}

root@problematic:/var/www# bash testfile.bash
testfile.bash: line 2: syntax error near unexpected token `$'\r''
'estfile.bash: line 2: `for (( c=1; c<=5; c++ ))
root@problematic:/var/www# echo $BASH_VERSION
4.2.37(1)-release
root@problematic:/var/www#

当然在其他计算机上,这个简单的脚本按预期工作,没有错误。

2 个答案:

答案 0 :(得分:2)

这显然未经测试,因为您尚未发布样本输入,但这是您应该使用的方法:

awk '
NR==FNR { if (!/#/) cnt[$1]=0; next }
{ cnt[$WHATEVER]++ }
END {
    PROCINFO["sorted_in"] = "@val_num_desc"
    for (name in cnt) {
        print name, cnt
        if (++c == 5) {
            break
        }
    }
}
' /home/luther/tipical_surnames.txt /home/luther/employers.txt

将“WHATEVER”替换为雇员姓氏存储在employer.txt中的字段编号。

上面使用GNU awk for sorted_in,其他awks我只是从输出循环中移除PROCINFO行和计数并将输出管道排序然后排序,例如:

awk '
NR==FNR { if (!/#/) cnt[$1]=0; next }
{ cnt[$WHATEVER]++ }
END {
    for (name in cnt) {
        print name, cnt
    }
}
' /home/luther/tipical_surnames.txt /home/luther/employers.txt | sort -k2,1nr | head -5

或任何正确的排序选项。

答案 1 :(得分:0)

我其实不太确定。我测试了你的脚本,通过复制和粘贴它,用想象的数据(/usr/share/dict/words),它似乎按预期工作。我想知道您发布的脚本与您正在运行的脚本之间是否存在差异?

在此期间,我冒昧地让它运行得更顺畅。请注意,在循环中,您是如何在每次迭代中读取整个姓氏文件的?此外,grep + wc -l可能会被grep -c取代。我还在-F的第一次调用中添加grep,因为模式(#)是固定字符串。员工档案中的grep使用\<$name\>来确保在$nameJohn时我们只收到Johns而没有Johnssons。

#!/bin/bash

employees_in="/usr/share/dict/words"
names_in="/usr/share/dict/words"

grep -v -F "#" "$names_in" | head -n 5 | cut -f 1 |
while read -r name; do
    count="$( grep -c "\<$names\> " "$employees_in" )"
    printf "name: %-10s\tcount: %d\n" "$name" "$count"
done

测试它:

$ bash script.sh
name: A             count: 1
name: a             count: 1
name: aa            count: 1
name: aal           count: 1
name: aalii         count: 1

注意:我只获得计数中的一个,因为字典(不足为奇)只包含唯一的单词。