在字符串与bash文本实用程序匹配后计算出现次数

时间:2011-05-25 10:02:44

标签: regex bash sed awk grep

我正在尝试使用一些很酷的conky配置来重新组织我的桌面。因为我是Emacs中org-mode的忠实粉丝,所以我想从org文件中删除任务,在那里我保存我的日常任务并将其显示为conky。假设我有这样的文件:

* first item
** subitem
** subitem
** subitem
* second item
** subitem
** subitem
* third item
** subitem
** subitem
** subitem
** subitem

我想创建一个我的任务摘要,这些任务将检查以*开头的所有任务并在其前面计算**个项目。然后我想以合适的方式提出这个问题:

* first item [3]
* second item [2]
* third item [4]

虽然我可以找到字符串的出现,但只有一个*grep开头:

grep "^\\* " foo.org

我可以使用{

计算**的出现次数
grep -c "^\\*\{2\}" foo.org

如何达到预期效果?当然,可以使用Python或Ruby,但我只想坚持使用bash实用程序。

2 个答案:

答案 0 :(得分:2)

在您提供的示例文件中:

awk '!/^*/{next}$1=="*"{sub("\\*+ ","");p=$0}$1="**"{c[p]+=1}END{for(i in c) printf "* %s [%s]\n", i ,c[i]-1}'

返回所需的输出。

* second item [2]
* first item [3]
* third item [4]

如果您需要对其进行排序,请将结果输入sort

awk command | sort -k2,2

答案 1 :(得分:1)

这不是我的第一选择,但你可以用纯粹的bash(没有叉子)做到这一点:

#!/bin/bash

set -u
unset HEADING LINE COUNT
COUNT=0
while read LINE; do
  if [[ "$LINE" =~ '^\* ' ]]; then
    #print previous, if it exists
    declare -p HEADING > /dev/null 2>&1 && echo "$HEADING [${COUNT}]"

    HEADING=$LINE
    COUNT=0
  elif [[ "$LINE" =~ '^\*\* ' ]]; then
    let COUNT++
  else
    echo "Unexpected input" 1>&2
  fi
done
echo "$HEADING [${COUNT}]"

要指出的事情:

  • [[ ... =~ ... ]]是允许正则表达式匹配的bash扩展
  • declare -p用于测试变量存在
  • 如果输入不是如上所述,那么脚本会做有趣的事情。空行,没有*或**前缀的行