bash - 匹配并选择字符串的最佳分数

时间:2012-10-09 23:02:31

标签: bash pattern-matching

我正在尝试使用bash脚本,需要帮助解决这个问题:
我在文本文件中有以下数据:(test.txt)

have.a.nice.day.a=42and55  
have.a.nice.day.b=0  
have.a.nice.day.c=55and67  
go.to.sleep.a=111  
go.to.sleep.b=2and122and33  
go.to.sleep.c=64  

我希望将字符串与其匹配分数和分隔符分数(在本例中为“和”)分开,然后从每个组中选择得分最高的字符串。
在这种情况下,对于组“go.to.leice.day”而言,它将是“have.a.nice.day.c”,对于组“go.to.sleep”,它将是“go.to.sleep.b”
所以我认为最好的办法是分离元素并递归地分配它们。像这样:

#!/bin/bash
names=$(cat test.txt | grep -o -P '.+(?==\d+)')
 for name in $names
 do
  echo -n "$name"" "
  scores=$(cat test.txt | grep -o -P '(?<='$name'=).+')
   for scores_group in $scores
   do
    single_score=$(echo $scores_group | grep -o -P '\d+') 
     for score in $single_score
     do
      echo -n "$score"" "
     done
     echo
   done
 done  
输出将是:

have.a.nice.day.a 42 55 
have.a.nice.day.b 0 
have.a.nice.day.c 55 67 
go.to.sleep.a 111 
go.to.sleep.b 2 122 33 
go.to.sleep.c 64  

但现在我不知道如何为每个小组找到最佳分数 感谢

1 个答案:

答案 0 :(得分:3)

因此,我认为您的实际问题是如何将“输入文本”标记为“输出”,并找到编号最大的行?

假设您的输出是输入,我将使用awk执行此操作:

$ awk '{name=$1; item=$1; sub(/\.[^.]+$/,"",name); sub(/.*\./,"",item); for (i=2; i<=NF; i++) {if($i>highest[name]){highest[name]=$i;which[name]=item}}} END{for(name in highest){printf("%s = %s = %s\n",name,which[name],highest[name])}}' input.txt
go.to.sleep = b = 122
have.a.nice.day = c = 67

或者,为了解释而分解:

{

  # Get the parts of the first field...
  name=$1; sub(/\.[^.]+$/,"",name);
  item=$1; sub(/.*\./,"",item);

  # Walk through the scores, record the highest in an array
  for (i=2; i<=NF; i++) {
    if ($i>highest[name]) {
      highest[name]=$i;
      which[name]=item;
    }
  }
}

# Now, step through the resultant array
END {
  for (name in highest) {
    printf("%s = %s = %s\n",name,which[name],highest[name]);
  }
}
这会吗?或者你真的想要在纯粹的bash中实现这个目标吗?如果是这样,上面的awk可以用下面的bash表示:

#!/bin/bash

declare -A highest
declare -A which

while read word scores; do
    name=${word%.*}
    item=${word##*.}
    set -- $scores
    while [[ -n "$1" ]]; do
        if [[ $1 -gt highest[$name] ]]; then
            highest[$name]=$1
            which[$name]=$item
        fi
        shift
    done
done < input.txt

for name in "${!highest[@]}"; do
    printf "%s = %s = %s\n" "$name" "${which[$name]}" "${highest[$name]}"
done