Используйте sed, чтобы скрыть шаблон для другого sed - PullRequest
0 голосов
/ 24 мая 2018

Я хотел бы, чтобы подход выполнял замену с использованием команды sed, которая экранировала «шаблон» (строку) для использования в другой команде sed. Этот процесс должен включать обработку шаблона многострочных строк.

Для иллюстрации приведу приведенный ниже код.Он отлично работает (пока хорошо проверено), но не работает, если у нас есть строки с несколькими строками (см. «STRING_TO_ESCAPE»).

#!/bin/bash

# Escape TARGET_STRING.
read -r -d '' STRING_TO_ESCAPE <<'HEREDOC'
    $N = "magic_quotes_gpc = <b>"._("On")."</b>";
    $D = _("Increase your server security by setting magic_quotes_gpc to 'on'. PHP will escape all quotes in strings in this case."); 
    $S = _("Search for 'magic_quotes_gpc' in your php.ini and set it to 'On'."); 
    $R = ini_get('magic_quotes_gpc'); 
    $M = TRUE;
    $this->config_checks[] = array("NAME" => $N , "DESC" => $D , "RESULT" => $R , "SOLUTION" => $S , "MUST" => $M );
HEREDOC
ESCAPED_STRING=$(echo "'${STRING_TO_ESCAPE}'" | sed 's/[]\/$*.^|[]/\\&/g')
ESCAPED_STRING=${ESCAPED_STRING%?}
TARGET_STRING=${ESCAPED_STRING#?}

# NOTE: The single quotes in "'${STRING_TO_ESCAPE}'" serve to prevent spaces 
# being "lost" at the beginning and end of the string! The manipulations with 
# "ESCAPED_STRING" are used to remove them. When we use sed with the file being 
# input (flag "-i") this problem does not occur.

# Escape REPLACE_STRING.
read -r -d '' STRING_TO_ESCAPE <<'HEREDOC'
    /* NOTE: "Magic_quotes_gpc" is no longer required. We taught GOsa2 to deal with it (see /usr/share/gosa/html/main.php). By Questor */
    /* Automatic quoting must be turned on */
    /* $N = "magic_quotes_gpc = <b>"._("On")."</b>";
    $D = _("Increase your server security by setting magic_quotes_gpc to 'on'. PHP will escape all quotes in strings in this case."); 
    $S = _("Search for 'magic_quotes_gpc' in your php.ini and set it to 'On'."); 
    $R = ini_get('magic_quotes_gpc'); 
    $M = TRUE;
    $this->config_checks[] = array("NAME" => $N , "DESC" => $D , "RESULT" => $R , "SOLUTION" => $S , "MUST" => $M ); */
HEREDOC
ESCAPED_STRING=$(echo "'${STRING_TO_ESCAPE}'" | sed 's/[]\/$*.^|[]/\\&/g')
ESCAPED_STRING=${ESCAPED_STRING%?}
REPLACE_STRING=${ESCAPED_STRING#?}

# Do the replace.
STRING_TO_MODIFY=$(cat file_name.txt)
MODIFIED_STRING=$(echo "'${STRING_TO_MODIFY}'" | sed 's/$TARGET_STRING/$REPLACE_STRING/g')
MODIFIED_STRING=${MODIFIED_STRING%?}
MODIFIED_STRING=${MODIFIED_STRING#?}

echo "$MODIFIED_STRING"

Спасибо!= D

1 Ответ

0 голосов
/ 24 мая 2018

Этот процесс должен включать обработку шаблона многострочных строк.

Я думаю, что вы лаете не на то дерево.Если вы пытаетесь сопоставить многострочный шаблон, то наиболее существенная проблема заключается не в том, как избежать шаблона, а в том, как написать сценарий sed, который будет успешно соответствовать чему-либо.

Проблема заключается в том,sed читает входные данные по одной строке за раз.Существуют различные способы сбора нескольких строк и работы с такими коллекциями, но вы должны сделать это явно в программе.Поэтому sed - плохой выбор для попытки сопоставления произвольного многострочного текста.Чтобы сделать вашу задачу выполнимой, вам нужно знать, сколько строк будет содержать шаблон, чтобы написать свою программу sed, которая будет соответствовать этому.Даже тогда это может быть лучше для Perl.

Обновление:

Поскольку мне нравится sed, вот пример того, как вы могли бы написатьsed Программа, которая соответствует многострочным шаблонам:

#!/bin/sed -f
# Build up a three-line window in the pattern space
:a
/\(.*\
\)\{2\}/! { N; ba; }

# A(nother) multiline pattern.  If the pattern fails to match then the
# first line of the pattern space is printed and deleted, then
# we loop back to reload.
/^The\
quick\
brown$/! { P; D; ba; }

# Do whatever we want to do in the event of a match
s/brown/red/

# If control reaches here then the whole pattern space is printed,
# and if any input lines remain then we start again from the beginning
# with an initially-empty pattern space.

Пример ввода:

$ ./ml.sed <<EOF
The
quick
brown
fox          
jumped over
the lazy dog.
EOF

Вывод:

The
quick
red
fox
jumped over
the lazy dog.

Обратите внимание, что переводы строк соответствуют обычным символам, но эти буквальные символы новой строки в шаблоне или тексте замены необходимо экранировать обычным образом по синтаксическим причинам.

Обновление 2 :

Вот вариант, который заменяет появленияиз трехстрочной последовательности

brown
fox          
jumped over

с трехстрочной последовательностью

red
pig          
is fat

.Конечно, есть много других способов сделать то же самое с sed, и один из других может быть предпочтительнее этого для ваших конкретных целей.

#!/bin/sed -f
:a
/\(.*\
\)\{2\}/! { N; ba; }

/^brown\
fox\
jumped over$/! { P; D; ba; }

s/.*/red\
pig\
is fat/
...