sed, заменяющий символ в файле

Мне нужно заменить один символ в /etc/request-key.conf

Формат файла:

###############################################################################
#
# Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
# Written by David Howells (dhowells@redhat.com)
#
# 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

Так что мне нужна третья последняя строка для перехода;

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

-;

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

Я пытался;

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

Bu i I просто нужно заменить -c на -t

3
задан 13 September 2019 в 18:10

1 ответ

Золотое правило в регулярных выражениях: меньше больше. Всегда пытайтесь найти самое простое выражение, которое достаточно для предназначения для строки поиска. Таким образом вместо того, чтобы пытаться соответствовать всей строке, ищите маленькую, но уникальную, строку:

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

Я сохранил Ваш файл как file и, как Вы видите, существует только один случай -c в файле. Таким образом, все, в чем Вы нуждаетесь, (отметьте -i.bak, это создаст файл резервной копии):

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

Если Вы хотите быть более благоразумными и удостовериться, что Вы соответствуете только своей целевой строке, не ища сначала, просто изменяетесь -c на любых строках, запускающихся с create cifs.spnego. Отметьте использование -E для расширенных регулярных выражений и использования \s+ (1 или более пробелов) вместо того, чтобы пытаться записать несколько пробелов:

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

Так как Вы не должны вносить изменения после -c, нет никакой причины попытаться соответствовать ему: меньше больше.


Причина Ваша отказавшая попытка состоит в том потому что * множитель в регулярных выражениях, это означает "0 или больше". Таким образом, когда Вы имеете cifs.spnego *cifs.upcall, это ищет cifs.spnego, затем 0 или больше пробелов, сопровождаемых cifs.upcall. Ваша строка, однако, была:

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

Для соответствия этому необходимо соответствовать cifs.spnego, затем пространство, затем a *, затем больше пробелов и другой *, затем /usr/sbin/ и только затем сделайте Вы имеете cifs.upcall. Для соответствия всем тем Вам было бы нужно (Вам нужно \* соответствовать символу *):

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

Или, так как меньше больше, просто:

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

.* означает "что-либо".

8
ответ дан 1 December 2019 в 13:14

Другие вопросы по тегам:

Похожие вопросы: