Подтвердить что ты не робот

Как проверить, изменил ли sed файл

Я пытаюсь найти умный способ выяснить, был ли файл, переданный sed, успешно изменен или нет.

В принципе, я хочу знать, был ли файл изменен или нет, не глядя на дату изменения файла.

Причина, по которой мне это нужно, - это то, что мне нужно сделать некоторые дополнительные вещи, если sed успешно заменил шаблон.

В настоящее время у меня есть:

    grep -q $pattern $filename
    if [ $? -eq 0 ]
    then
        sed -i s:$pattern:$new_pattern: $filename
                # DO SOME OTHER STUFF HERE
    else
        # DO SOME OTHER STUFF HERE
    fi

Вышеприведенный код немного дороже, и я хотел бы использовать некоторые хаки здесь.

4b9b3361

Ответ 1

Вместо awk можно использовать

awk "/$pattern/"' { gsub( "'"$pattern"'", "'"$repl"'" ); t=1 }
    1; END{ exit( !t )}'

Я игнорирую функцию -i: вы можете использовать оболочку, если необходимо, перенаправить.

Ответ 2

Немного опоздал на вечеринку, но в интересах других, я обнаружил, что флаг w был именно тем, что я искал.

sed -i "s/$pattern/$new_pattern/w changelog.txt" "$filename"
if [ -s changelog.txt ]; then
    # CHANGES MADE, DO SOME STUFF HERE
else
    # NO CHANGES MADE, DO SOME OTHER STUFF HERE
fi

changelog.txt будет содержать каждое изменение (т.е. измененный текст) на собственной строке. Если изменений не было, changelog.txt будет равен нулю.

Действительно полезный ресурс sed (и где я нашел эту информацию) http://www.grymoire.com/Unix/Sed.html.

Ответ 3

Я считаю, что вы можете найти эти расширения GNU sed

t label

If a s/// has done a successful substitution since the last input line
was read and since the last t or T command, then branch to label; if
label is omitted, branch to end of script.

и

q [exit-code]

Immediately quit the sed script without processing any more input, except 
that if auto-print is not disabled the current pattern space will be printed. 
The exit code argument is a GNU extension.

Кажется, именно то, что вы ищете.

Ответ 4

Это может сработать для вас (GNU sed):

sed -i.bak '/'"$old_pattern"'/{s//'"$new_pattern"'/;h};${x;/./{x;q1};x}' file || echo changed

Пояснение:

  • /'"$old_pattern"'/{s//'"$new_pattern"'/;h}, если пространство шаблонов (PS) содержит old pattern, замените его на new pattern и скопируйте PS в пространство удержания (HS).
  • ${x;/./{x;q1};x} при встрече с последней строкой, поменяйте на HS и проверьте его на наличие любой строки. Если строка найдена в HS (т.е. произошла замена), замените исходный PS и выйдите с помощью кода выхода 1, в противном случае замените исходный PS и выйдите с кодом выхода 0 (по умолчанию).

Ответ 5

Вы можете разбить исходный файл на вывод sed, чтобы увидеть, изменилось ли оно:

sed -i.bak s:$pattern:$new_pattern: "$filename"
if ! diff "$filename" "$filename.bak" &> /dev/null; then
  echo "changed"
else
  echo "not changed"
fi
rm "$filename.bak"

Ответ 6

Я знаю, что это старый вопрос, и использование awk вместо sed - это, пожалуй, лучшая идея, но если кто-то хочет придерживаться sed, идея заключается в использовании флага -w. Аргумент файла для флага w содержит только строки с совпадением. Поэтому нам нужно только проверить, что он не пуст.