skip to Main Content

I’d like to use sed to modify a Debian control file to change the dependencies of a particular package.

The file contains metadata for several packages, where entry looks like this:

Package: linux-image-generic
Architecture: i386 amd64 armhf arm64 powerpc ppc64el s390x
Section: kernel
Provides: ${dkms:zfs-modules} ${dkms:virtualbox-guest-modules} ${dkms:wireguard-linux-compat-modules}
Depends: ${misc:Depends}, linux-image-${kernel-abi-version}-generic, linux-modules-extra-${kernel-abi-version}-generic [i386 amd64 arm64 powerpc ppc64el s390x], linux-firmware, intel-microcode [amd64 i386], amd64-microcode [amd64 i386]
Recommends: thermald [i386 amd64]
Description: Generic Linux kernel image
 This package will always depend on the latest generic kernel image
 available.

Package: linux-tools-generic
Architecture: i386 amd64 armhf arm64 powerpc ppc64el s390x
Section: kernel
Provides: linux-tools
Depends: ${misc:Depends}, linux-tools-${kernel-abi-version}-generic
Description: Generic Linux kernel tools
 This package will always depend on the latest generic kernel tools
 available.

I would like to find the line that matches Package: linux-image-generic, then modify the following line that matches Depends:, for instance by performing s/linux-image-/linux-image-unsigned-/.

3

Answers


  1. Chosen as BEST ANSWER

    Here's my solution that modifies the Depends: line, but only within the linux-image-generic section.

    This solution for GNU sed, but a slight modification makes it work for BSD sed, noted below.

    sed '/^Package: linux-image-generic$/,/^$/{/^Depends:/ s/linux-image-/linux-image-unsigned-/}' debian/control
    

    It starts with a range address that matches from the beginning of the package metadata up to the blank line after the package block.

    /^Package: linux-image-generic$/,/^$/
    

    Then it uses a {} to apply a command within this range:

    /^Depends:/ s/linux-image-/linux-image-unsigned-/
    

    The first part here, /^Depends:/, is a regular expression address that selects only the line(s) that begin with Depends:.

    Lastly, the s command performs the substitution on the selected line.


    BSD sed (on macOS, etc.) has an additional syntactic rule for function lists { ... }:

    The terminating “}” must be preceded by a newline, and may also be preceded by white space.

    We need to insert a newline before the }, for example by using the $'n' ANSI-C string in Bash:

    sed '/^Package: linux-image-generic$/,/^$/{/^Depends:/ s/linux-image-/linux-image-unsigned-/'$'n''}' debian/control
    

    As an aside, the path to finding this solution was to research sed commands that operate on other file formats with similar syntaxes, like INI files.


  2. The sed solution you found is perfect. For completeness, with GNU awk instead of sed:

    awk -v RS= -v ORS='nn' '/^Package: linux-image-generic/ {
      $0 = gensub(/(nDepends:[^n]*linux-image-)/,"&unsigned-",1)} 1' file
    

    If the input record separator (RS) is the empty string records are separated by empty lines. So each section of your file is a record. gensub does the substitution.

    Login or Signup to reply.
  3. This might work for you (GNU sed):

    sed '/Package: linux-image-generic/{:a;n;/Depends:/!ba;s/linux-image-/&unsigned-/}' file
    

    Find line containing Package: linux-image-generic then continue reading lines until one containing Depends: and substitute linux-image- with linux-image-unsigned-.

    N.B. This assumes the package stanza contains Depends:, if not, then:

    sed -E '/Package:/{h;:a;n;/Package:/{h;ba};/Depends/!ba;G
           s/(linux-image-)(.*)n.*Package: linux-image-generic/1unsigned-2/}' file
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search