Подсчет вхождений после совпадения строки с помощью утилит bash text - PullRequest
5 голосов
/ 25 мая 2011

Я пытаюсь реорганизовать свой рабочий стол с помощью какой-нибудь крутой конки конфигурации.Так как я очень большой поклонник режима org в Emacs, я бы хотел вывести задачи из файла 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 ]

2 голосов
/ 25 мая 2011

В файле примера, который вы дали:

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 голос
/ 25 мая 2011

Это не будет моим первым выбором, но вы можете сделать это в чистом виде (без вилок):

#!/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 используется для проверки существования переменной
  • Скрипт будет делать забавные вещи, если ввод не такой, как описано, например, пустые строки, строкибез префикса * или **
...