0

I'm making a Unix database in a plain text with GNU Recutils. With the following script I get a books list of a selected category:

recsel -t book -e "Category='$1'" "$RECFILE" | recfmt -f bycat.templ

The output is the following:

1: Book title
2: Book title
55: Book title
128: Book title

The file bycat.templ has the following content:

{{Id}}: {{Title}} (read: {{Read}})

It seems it's impossible to define the alignment to the right side from this file, according to the manual.

So I try to find a Unix solution, probably using printf, awk, xargs or perhaps a for bucle for every line. I don't know how to achieve this.

The desired output:

  1: Book title
  2: Book title
 55: Book title
128: Book title

2 Answers 2

1

Here you are:

File: book.awk

BEGIN {
    FS = ":"
}
{
    id = $1
    $1 = ""
    sub(/^ +/, "", $0)
    printf("%3d: %s\n", id, $0)
}

Execution:

recsel ... | recfmt ... | awk -f book.awk

Output:

  1: Book title
  2: Book title
 55: Book title
128: Book title
5
  • Totally awesome! Thanks!
    – Unix
    Sep 5, 2021 at 22:40
  • 1
    I think printf("%3d: will align numeric values to the right for the first 999 books. Don't know the size of the database and if it poses a problem.
    – Gounou
    Sep 6, 2021 at 0:58
  • It would be interesting to get the length of the highest value and apply this length as variable, in substitution for the 3 number. I'm not sure if I should get the length for this output (1st column) or directly the highest value of the Id field (with bash and the command recsel), mixing bash and awk.
    – Unix
    Sep 6, 2021 at 6:29
  • I'm not sure but I think it will remove the colon " : " if there is one in the book title (or elsewhere after the ID). Maybe it needs an Output Field Separator (OFS).
    – Gounou
    Sep 6, 2021 at 12:49
  • @Gounou correct (mostly), it'll replace every : in a book title with a blank char. It'd be more efficient to just not cause that replacement to occur than set OFS so the :s got replaced with themselves but that definitely would be one workaround except that you'd then need to change the sub(/^ +/ too since the line would then start with a colon instead of a blank. The most important caveat here IMHO is that it will fail if any of the IDs can be 4 or more digits long and leave leading blanks if they can be 1 or 2 digits long.
    – Ed Morton
    Sep 24, 2021 at 21:58
1

A 2-pass approach using any awk in any shell on every Unix box no matter how may digits are in the ID and no matter which characters can be present in a title (including :):

$ cat tst.awk
{
    id = title = $0
    sub(/ *:.*/,"",id)
    sub(/[^:]*: */,"",title)
}
NR==FNR {
    wid = length(id)
    maxWid = (maxWid > wid ? maxWid : wid)
    next
}
{ printf "%*s: %s\n", maxWid, id, title }

$ awk -f tst.awk file file
  1: Book title
  2: Book title
 55: Book title
128: Book title
2
  • file file -> file ?
    – Gounou
    Sep 24, 2021 at 21:43
  • 1
    @Gounou No, as I mentioned it's a 2-pass approach. First pass to determine the longest width of the ID field, second pass to print using that width.
    – Ed Morton
    Sep 24, 2021 at 21:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .