Ответ 1
Вместо awk
можно использовать
awk "/$pattern/"' { gsub( "'"$pattern"'", "'"$repl"'" ); t=1 }
1; END{ exit( !t )}'
Я игнорирую функцию -i
: вы можете использовать оболочку, если необходимо, перенаправить.
Я пытаюсь найти умный способ выяснить, был ли файл, переданный 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
Вышеприведенный код немного дороже, и я хотел бы использовать некоторые хаки здесь.
Вместо awk
можно использовать
awk "/$pattern/"' { gsub( "'"$pattern"'", "'"$repl"'" ); t=1 }
1; END{ exit( !t )}'
Я игнорирую функцию -i
: вы можете использовать оболочку, если необходимо, перенаправить.
Немного опоздал на вечеринку, но в интересах других, я обнаружил, что флаг 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.
Я считаю, что вы можете найти эти расширения 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.
Кажется, именно то, что вы ищете.
Это может сработать для вас (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
(по умолчанию).Вы можете разбить исходный файл на вывод 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"
Я знаю, что это старый вопрос, и использование awk вместо sed - это, пожалуй, лучшая идея, но если кто-то хочет придерживаться sed, идея заключается в использовании флага -w. Аргумент файла для флага w содержит только строки с совпадением. Поэтому нам нужно только проверить, что он не пуст.