I have a .toc (table of contents file) from my .tex  document.It contains a lot of lines and some of them have the form\contentsline {part}{Some title here\hfil }{5}\contentsline {chapter}{\numberline {}Person name here}{5}I know how to grep for part and for chapter. But I'd like to filter for those lines and have the output in a csv file like this:{Some title here},{Person name here},{5}or with no bracesSome title here,Person name here,51. For sure the number (page number) in the last pair {} is the same for both two lines, so we can filter only the second one.2. Note that some empty pair {} could happens or also could contain another pair {}. For example, it could be\contentsline {part}{Title with math $\frac{a}{b}$\hfil }{15}which should be filtered asTitle with math $\frac{a}{b}$edit 1: I was able to obtain the numbers without braces at end of line usinggrep '{part}' file.toc | awk -F '[{}]' '{print $(NF-1)}'edit 2: I was able to filter the chapter lines and remove the garbage withgrep '{chapter}' file.toc | sed 's/\\numberline//' | sed 's/\\contentsline//' | sed 's/{chapter}//' | sed 's/{}//' | sed 's/^ {/{/'and the output without blank spaces was    {Person name here}{5}edit 3: I was able to filter for part and clean the output with    \contentsline {chapter}{\numberline {}Person name here}{5}which returns{Title with math $\frac{a}{b}$}{15}
How to filter pair of braces
awk;grep
This is using GNU awk, using POSIX awk would be very troublesome (lack of gensub, which I use more than once).#!/usr/bin/env gawkfunction join(array, result, i){    result = array[0];    end = length(array) - 1;    for (i = 1; i <= end; i++)        result = result , array[i];    return result;}function push(arr, elem){    arr[length(arr)] = elem;}# split(, arr) is a horribly unreadable way to clear an arrayBEGIN { split(, arr); }/{part}|{chapter}/ {    l = gensub(.*{(.+)}{(.+)}{([0-9]+)}$, \\1,\\3,\\2, g);    if (part == substr(l, 0, 4)) {        if (length(arr) > 0) { print join(arr); }        split(, arr);        push(arr, gensub(^(.*),(.*),(.*)$, \\2,\\3,g, l));    } else {        push(arr, gensub(^(.*),(.*),(.*)$, \\3,g, l));    }}END { print join(arr); }This uses the fact that regexes are greedy, so the matches will get the full line each time.  It took more effort than I though at first.With the following input:\contentsline {part}{Some title here\hfil }{5}\contentsline {chapter}{\numberline {}Person name here}{5}blah blah\contentsline {chapter}{\numberline {}Person name here}{5}blah blahblah blah\contentsline {chapter}{\numberline {}Person name here}{5}\contentsline {chapter}{\numberline {}Person name here}{5}blah blahblah blah\contentsline {chapter}{\numberline {}Person name here}{5}\contentsline {chapter}{\numberline {}Person name here}{5}\contentsline {part}{Some title here\hfil }{7}\contentsline {chapter}{\numberline {}Person name here}{7}blah blahblah blah\contentsline {chapter}{\numberline {}Person name here}{7}blah blah\contentsline {part}{Some title here\hfil }{9}blah blahblah blah\contentsline {chapter}{\numberline {}Person name here}{9}We produce with cat input | awk -f the_above_script.awk:5,Some title here\hfil ,\numberline {}Person name here,\numberline {}Person name here,\numberline {}Person name here,\numberline {}Person name here,\numberline {}Person name here,\numberline {}Person name here7,Some title here\hfil ,\numberline {}Person name here,\numberline {}Person name here9,Some title here\hfil ,\numberline {}Person name hereThe page number is taken from the {part} then any {chapter} that happens after the {part} is included.  This allows for several chapters inside parts of a book.