Я не использую Ubuntu, но не думаю, что это возможно в более новых версиях glibc. См. commit .
Если не считать написания собственного детектора разрушения стека, конечно.
Вы можете посмотреть источник функции, печатающей это сообщение:
void
__attribute__ ((noreturn))
__fortify_fail_abort (_Bool need_backtrace, const char *msg)
{
/* The loop is added only to keep gcc happy. Don't pass down
__libc_argv[0] if we aren't doing backtrace since __libc_argv[0]
may point to the corrupted stack. */
while (1)
__libc_message (need_backtrace ? (do_abort | do_backtrace) : do_abort,
"*** %s ***: %s terminated\n",
msg,
(need_backtrace && __libc_argv[0] != NULL
? __libc_argv[0] : ""));
}
Эта функция будет вызываться с помощью need_backtrace = False
из __stack_chk_fail
, которая сама вызывается из кода защиты стека, скомпилированного в двоичный файл.
В три шага, используя синтаксис sed
, совместимый с /usr/bin/sed
в macOS, и либо bash
, либоzsh
(две основные оболочки в текущих системах macOS):
sed -n '/hello/=' sample.txt |
sed -e '$!d' -e $'s/.*/&r sample1.txt\\\n&d/' |
sed -f /dev/stdin sample.txt
Здесь используется sed
в три шага:
Находит все строки в sample.txt
, соответствующие hello
, и выводит номера строк, соответствующие этим строкам.
Удаляет все, кроме последнего номера строки, выведенные на первом шаге (с помощью $!d
, «если это не последняя строка, удалите ее» )и создает две -строки sed
скрипт, который изменит последнюю совпадающую строку, сначала прочитав sample1.txt
, а затем удалив исходную строку. Учитывая, что последнее совпадение hello
находится в строке 3 в исходном файле, этот скрипт будет выглядеть как
3r sample1.txt
3d
Применяет созданный скрипт sed
к файлу sample.txt
.
Если вы хотите сделать редактирование «в -месте», чтобы изменить исходный sample.txt
, тогда используйте
sed -n '/hello/=' sample.txt |
sed -e '$!d' -e $'s/.*/&r sample1.txt\\\n&d/' |
sed -i '' -f /dev/stdin sample.txt
Тот же набор команд, но с использованием ваших переменных $sample_file_path
и $sample_file_path_1
для двух путей к файлам:
sed -n '/hello/=' "$sample_file_path" |
sed -e '$!d' -e 's,.*,&r '"$sample_file_path_1"$'\\\n&d,' |
sed -i '' -f /dev/stdin "$sample_file_path"
Обратите внимание, что я изменил разделители во второй команде с /
на ,
, так как путь к файлу содержит косые черты. Вы можете использовать любой символ в качестве разделителя в команде s///
, который не является частью регулярного выражения или замещающего текста.
Попробуйте комбинацию tac
и awk
:
tac sample.txt \
| awk -v replacement="$(tac sample1.txt)" '/hello/ && !n++ {gsub(/hello/,replacement,$0)}1' \
| tac
Обратите внимание, что это также заменит часть hello
из nothello
. Если вы хотите заменить только независимые hello
, вам нужно добавить границы слов в шаблон:/\<hello\>/
вместо/hello/
Мы можем использовать утилиту редактора потока sed
, чтобы получить желаемый результат.
sed -n '
/hello/!{
H;1h;$!d;g
s///w file.tmp
t a
p;q
}
x;1!p;$!d
:a
r file2
' file1
sed -e '1d' file.tmp
hello
hello
, он печатает то, что было сохранено в ожидании, и снова запускает цикл. EOF
или последней строке мы печатаем пробелы и шаблоны. Или другой способ —tac
-perl
-tac
конвейер:
tac file1 |
perl -0777 -pe 's?hello\n?qx/tac file2/?e' - |
tac
С помощью одного вызова + с использованиемPosix
-ly конструкций sed
мы можем сделать так, как показано. USP этого подхода заключается в том, что код sed сам генерирует файл, который он позже будет считывать в поток печати.
sed -n '
/\n/{
s/.$//w file.tmp
b a
}
/hello/!{
H;1h;$!d
s/.*//;x
//!{p;q;}
G;D
}
x;1!p;$!d;:a
r file2
r file.tmp
' file1
Краткое объяснение того, как это работает:
//!{p;q;}
. На данном этапе мы уже находимся в eof и проверили регулярное выражение /hello/, поэтому можем повторно использовать его как //
. file2
, так как это ПОСЛЕДНЯЯ строка /hello/. Но ложка дегтя в том, что нам нужна другая часть (не приветственных строк ). Если бы мы просто сделали r file2
, это поместило бы содержимое в конец. Поэтому мы должны придумать что-то, чтобы преодолеть это. Что мы делаем, так это сохраняем эти не приветственные строки в файле, а затем выполняем r tmpfile
. ПБМ решил.