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
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 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 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 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 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 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 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 at 21:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.