sed replace не может заменить строку, если есть квадратная скобка - PullRequest
1 голос
/ 13 марта 2019

Моя переменная результата содержит следующее:

auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=888
auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=888

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

echo "$result" |
   while IFS= read -r line;
   do
      newValue=""
      for ii in $line
      do
         if [[ "$ii" != *"unlock_time"* ]]; then
            newValue="$newValue $ii"
         fi
      done
      newValue="$newValue unlock_time=900"
      sed -i "s/$line/$newValue/g" $password_auth
      echo " Line    : [ $line ]"
      echo "newValue : [ $newValue ]"
   done

Выходные данные показывают это:

 Line    : [  auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=900 ]
newValue : [  auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=900 ]
 Line    : [ auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=888 ]
newValue : [  auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=900 ]

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

Но когда я проверяю файл, я вижу, что второй экземпляр unlock_time по-прежнему равен 888из 900.

Примечание: я не могу глобально заменить unlock_time, поэтому я храню строки, которые нуждаются в обновлении в результате.

Есть ли что-то, что пропущено в цикле?

Обновление: я попытался запустить команды sed в командной строке:

sed -i "s/auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=900/auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=999/g" temp  <-- This works
sed -i "s/auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=9/auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=900/g" temp   <-- This doesn't update file but doesn't throw an error either

Команда работает в командной строке, когда я помещаю escape-символы вокруг [default = die].Но как мне это сделать, если я делаю это через скрипт?

1 Ответ

1 голос
/ 13 марта 2019

Вы пытаетесь найти постоянную.Запрещается сопоставление регулярных выражений через слои цитирования.Вот более простой метод perl (для демонстрационных целей обернут в bash):

#!/bin/bash

result="auth required pam_faillock.so preauth silent audit deny=3 even_deny_root fail_interval=888 unlock_time=888
auth [default=die] pam_faillock.so authfail audit deny=3 even_deny_root fail_interval=888 unlock_time=888"

# create a file to play with
echo "$result" > testfile

echo "$result" | perl -i -pe '
    BEGIN { @find = <STDIN> }
    for $str (@find) {
        s/(\bunlock_time)=\d+/$1=900/ if $_ eq $str;
    }
' testfile

# check the result
cat testfile
  • -i выполняет редактирование на месте, как sed
  • -p, оборачивает цикл while для чтения каждогострока, так что явная не нужна и выводит строку после возможного изменения (немного похоже на sed)
  • секция BEGIN инициализирует массив строк для поиска (из результата)
  • для каждой строки тестового файла ($_), for сравнивает ее со всеми строками, а if есть буквальное совпадение (eq), выполняет поиск и замену регулярных выражений для параметра unlock_time
...