1

The goal is to get the version of a source package in a reprepro-based deb repository.

Since the tracking of source packages is still experimental in reprepro, the list command has issues with --list-format option and thus cannot be used in this use case.

An excerpt of the output of the command to print out all information about tracked source packages is:

...

Distribution: buster
Source: linux-latest
Version: 102
Files:
 pool/stable/l/linux-latest/linux-doc_4.19+102_all.deb a 2
 pool/stable/l/linux-latest/linux-headers-amd64_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-headers-cloud-amd64_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-headers-rt-amd64_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-amd64_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-amd64-dbg_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-cloud-amd64_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-cloud-amd64-dbg_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-rt-amd64_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-rt-amd64-dbg_4.19+102_amd64.deb b 1
 pool/stable/l/linux-latest/linux-perf_4.19+102_all.deb a 2
 pool/stable/l/linux-latest/linux-source_4.19+102_all.deb a 2

Distribution: buster
Source: linux-latest
Version: 103
Files:
 pool/stable/l/linux-latest/linux-doc_4.19+103_all.deb a 0
 pool/stable/l/linux-latest/linux-headers-amd64_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-headers-cloud-amd64_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-headers-rt-amd64_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-amd64_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-amd64-dbg_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-cloud-amd64_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-cloud-amd64-dbg_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-rt-amd64_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-image-rt-amd64-dbg_4.19+103_amd64.deb b 1
 pool/stable/l/linux-latest/linux-perf_4.19+103_all.deb a 2
 pool/stable/l/linux-latest/linux-source_4.19+103_all.deb a 2

...

The goal here is to get the version of for instance linux-latest source package using for example the binary package name linux-source_4.19+103_all.deb by extracting all lines between:

1) a multi-line pattern:

Distribution: buster
Source: linux-latest

2) a string pattern:

linux-source_4.19+103_all.deb

The distribution name, source package name and binary package names are variable, so the number of captured lines is variable, but the base layout remains constant.

For that same reason, it seems that pcre2grep --multiline cannot be used here.

I cannot see a way to use multi-line patterns with awk or sed, although there must be a way, at least with awk.

Other stackoverflow answers don't seem to apply here:

Any suggestion?

  • You could use multi line matching, but in your case you don't need to. Just use a simple awk script that sets variables based on `Distribution` and `Source`. Whenever you find a package name, print the variables and the package version. – oliv Feb 20 '19 at 13:51

2 Answers2

1

It's not entirely clear what you're trying to do but i think you're saying you want to print the version value when a specific string appears in the record. If so that's just:

$ awk -v str='linux-source_4.19+103_all.deb' -F': *' '{f[$1]=$2} index($0,str){print f["Version"]}' file
103

If you wanted to also test for the specific distribution and source that's just a tweak:

$ awk -v str='linux-source_4.19+103_all.deb' -v dist='buster' -v src='linux-latest' -F': *' '
    { f[$1] = $2 }
    (f["Distribution"]==dist) && (f["Source"]==src) && index($0,str) { print f["Version"] }
' file
103

If you need something different then edit your question to clarify your requirements.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Your answer is almost perfect, except for un unmentioned use-case: there is an issue when the 'Version' field contains the character ':' which is used in the --field-separator. For instance, bind9 may have the version '1:9.11.5.P4+dfsg-1'. In that case, your answer needs to be modified by replacing -F': *' with **-F'':[ \n]''**. (I tried to use a character class in -F ':[[:space]]', but for some reason, the latter does not work at all). – jean-christophe manciot Mar 10 '19 at 10:14
  • `-F ':[[:space]]'` in your comment is missing the final `:` before `]]` but all you need is to change `-F': *` to `-F': '` if there's always just one blank or `-F': +'` if there can be multiple blanks. There will never be a `\n` within any record since we're reading one line at a time so the `\n`s from the input are being consumed as the RSs. – Ed Morton Mar 10 '19 at 18:49
0

This might work for you (GNU sed):

sed '/^Distribution: buster$/{:a;N;/\n\s*$/!ba;/^Source: linux-latest$/Ms/.*Version: \(\S\+\).*/\1/p};d' file

Gather up lines for a particular Distribution and use pattern matching to then extract the required Version.

This can be generalised for any Distribution collection of lines:

sed '/^Distribution/{:a;N;/\n$/!ba;/linux-source_4.19+103_all.deb/s/.*Version: \(\S\+\).*/\1/p};d' file

Thus the first solution could be written:

sed '/^Distribution/{:a;N;/\n$/!ba;/Distribution: buster\nSource: linux-latest/s/.*Version: \(\S\+\).*/\1/p};d' file

or if you prefer:

sed '/^Distribution/{:a;N;/\n$/!ba;/^Distribution: buster$/M!b;/^Source: linux-latest$/M!b;s/.*Version: \(\S\+\).*/\1/p};d' file

N.B. Care must be taken to quote any metacharacters that may be in the matching string i.e. characters such as []*. must be quoted e.g. [ becomes \[.

potong
  • 55,640
  • 6
  • 51
  • 83