4

I need to replace a single character in a/etc/request-key.conf

The file format is;

###############################################################################
#
# Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
# Written by David Howells ([email protected])
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version
# 2 of the License, or (at your option) any later version.
#
###############################################################################


###############################################################################
#
# We can run programs or scripts
# - Macro substitutions in arguments:
#   %%...   %...
#   %o  operation name
#   %k  ID of key being operated upon
#   %t  type of key being operated upon
#   %d  description of key being operated upon
#   %c  callout info
#   %u  UID of requestor
#   %g  GID of requestor
#   %T  thread keyring of requestor (may be 0)
#   %P  process keyring of requestor (may be 0)
#   %S  session keyring of requestor (may be the user's default session)
#
################################################################################

#OP TYPE    DESCRIPTION CALLOUT INFO    PROGRAM ARG1 ARG2 ARG3 ...
#====== ======= =============== =============== ===============================
create  dns_resolver *      *               /sbin/key.dns_resolver %k
create  user    debug:*     negate      /bin/keyctl negate %k 30 %S
create  user    debug:*         rejected        /bin/keyctl reject %k 30 %c %S
create  user    debug:*         expired         /bin/keyctl reject %k 30 %c %S
create  user    debug:*         revoked         /bin/keyctl reject %k 30 %c %S
create  user    debug:loop:*    *       |/bin/cat
create  user    debug:*     *       /usr/share/keyutils/request-key-debug.sh %k %d %c %S
create  cifs.spnego *   *       /usr/sbin/cifs.upcall -c %k
create  dns_resolver    *   *       /usr/sbin/cifs.upcall %k
negate  *   *       *       /bin/keyctl negate %k 30 %S

So I need the 3rd last line to go from;

create cifs.spnego * * /usr/sbin/cifs.upcall -c %k

to;

create cifs.spnego * * /usr/sbin/cifs.upcall -t %k

I have tried;

sed -i 's/^\(create cifs.spnego *cifs.upcall\) \(%k\)/\1 -t \2/' /etc/request-key.conf

Bu treally I just need to replace the -c with a -t

1 Answer 1

9

The golden rule in regular expressions is: less is more. Always try and find the simplest expression that is sufficient to target your search string. So instead of trying to match the entire line, look for a small, but unique, string:

$ grep -- -c file
create  cifs.spnego *   *       /usr/sbin/cifs.upcall -c %k

I saved your file as file and, as you can see, there is only one case of -c in the file. So all you need is (note the -i.bak, that will create a backup file):

sed -i.bak 's/-c/-t/' /etc/request-key.conf

If you want to be more prudent and make sure you match only your target line without searching first, just change the -c on any lines starting with create cifs.spnego. Note the use of -E for extended regular expressions and using \s+ (1 or more whitespace) instead of trying to write multiple spaces:

sed -Ei.bak 's/^(create\s+cifs\.spnego.*cifs.upcall\s+)-c/\1 -t/' /etc/request-key.conf

Since you don't need to make any changes after the -c, there is no reason to try and match it: less is more.


The reason your attempt failed is because * is a multiplier in regular expressions, it means "0 or more". So when you have cifs.spnego *cifs.upcall, that looks for cifs.spnego, then 0 or more spaces, followed by cifs.upcall. Your line, however, was:

create  cifs.spnego *   *       /usr/sbin/cifs.upcall  -t %k

To match that, you need to match cifs.spnego, then a space, then a *, then more spaces, and another *, then /usr/sbin/ and only then do you have cifs.upcall. To match all of those, you would need (you need \* to match the character *):

/^create  cifs.spnego \*   \*       cifs.upcall/

Or, since less is more, simply:

/^create  cifs.spnego .*cifs.upcall/

The .* means "anything".

3
  • I think you want s/-c/-t not s/-c/-k/ if I read the project scope correctly. Still +1 for "less is more". Sep 13, 2019 at 15:09
  • 1
    I often favor separating the context pattern from the replacement pattern in situations like this - for example sed '/cifs.spnego/ s/-c/-t/' Sep 13, 2019 at 15:12
  • @steeldriver yes, that makes a lot of sense.
    – terdon
    Sep 13, 2019 at 15:20

You must log in to answer this question.

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