Есть похожие вопросы:
Но они просят решить какие-то конкретные проблемы, а не получить общее решение.
Как должна выглядеть функция в сценариях bash для вставки строки (или символа) в другую строку по указанному индексу? Решения, оптимизированные по производительности, приветствуются в первую очередь.
Примеры с входными параметрами и ожидаемыми результатами для требуемой функции/процедуры:
string: "/etc /bin"
string to insert: "/tmp "
position index to insert: 0 (beginning of string)
expected result: "/tmp /etc /bin"
string: "/etc /bin"
char to insert: "|"
position index to insert: 2
expected result: "/e|tc /bin"
string: "/tmp /etc"
string to insert: " /bin"
position index to insert: 9 (end of string)
expected result: "/tmp /etc /bin"
string: "/tmp /etc /bin"
string to insert: "[ ]"
position index to insert: 7
expected result: "/tmp /e[ ]tc /bin"
Связанный вопрос:
Этот вопрос является частью проекта, связанного с другим моим вопросом: Как получить текст из текущей строки в указанной позиции курсора до и после указанных граничных символов?


cat insert_at_position.sh
#!/bin/bash
insert_at_position() {
local input_string=$1; shift
local insert_string=$1; shift
local position=$1; shift
local result = "${input_string:0:$position}$insert_string${input_string:$position}"
echo "$result"
}
assert_equals() {
local error_message=$1; shift
local expected_result=$1; shift
local actual_result=$1; shift
if [ "$expected_result" != "$actual_result" ]; then
printf "%s\n" "$error_message; Expected: $expected_result; Actual: $actual_result"
fi
}
test_insert_at_position() {
local test_line = "/etc /bin"
local expected = "/e|tc /bin"
local actual=$(insert_at_position "$test_line" "|" 2)
assert_equals "test_insert_cursor_char-p2 failed" "$expected" "$actual"
local test_line = "/tmp /etc"
local expected = "/tmp /etc /bin"
local actual=$(insert_at_position "$test_line" " /bin" 9)
assert_equals "test_insert_cursor_char-p9 failed" "$expected" "$actual"
local test_line = "/tmp /etc /bin"
local expected = "/tmp /e[ ]tc /bin"
local actual=$(insert_at_position "$test_line" "[ ]" 7)
assert_equals "test_insert_cursor_char-p7 failed" "$expected" "$actual"
local test_line = "/etc /bin"
local expected = "/tmp /etc /bin"
local actual=$(insert_at_position "$test_line" "/tmp " 0)
assert_equals "test_insert_cursor_char-p0 failed" "$expected" "$actual"
local test_line = "/etc /bin"
local expected = "/tmp"
local actual=$(insert_at_position "$test_line" "/tmp " 0)
assert_equals "test_insert_cursor_char - here fail is expected" "$expected" "$actual"
}
test_insert_at_position
insert_at_position — функция, которая вставляет строку в строку по указанному индексу.test_insert_at_position — юнит-тесты для этой функцииassert_equals — используется в test_insert_at_position, показывает сообщение об ошибке, если конкретный модульный тест не удался.Ниже та же функция, но выполненная в виде процедуры с параметром out_result, содержащим результат. Для его вызова не требуется Command Substitution $() и связанное с ним создание подоболочки. Но тем не менее производительность этих функций примерно одинакова.
cat insert_at_position.sh
#!/bin/bash
assert_equals() {
local error_message=$1; shift
local expected_result=$1; shift
local actual_result=$1; shift
if [ "$expected_result" != "$actual_result" ]; then
printf "%s\n" "$error_message; Expected: $expected_result; Actual: $actual_result"
fi
}
insert_at_position() {
local input_string=$1; shift
local insert_string=$1; shift
local position=$1; shift
declare -n out_result=$1; shift
out_result = "${input_string:0:$position}$insert_string${input_string:$position}"
}
test_insert_at_position() {
test_line = "/etc /bin"
expected = "/e|tc /bin"
insert_at_position "$test_line" "|" 2 actual
assert_equals "test_insert_cursor_char-p2 failed" "$expected" "$actual"
test_line = "/tmp /etc"
expected = "/tmp /etc /bin"
insert_at_position "$test_line" " /bin" 9 actual
assert_equals "test_insert_cursor_char-p9 failed" "$expected" "$actual"
test_line = "/tmp /etc /bin"
expected = "/tmp /e[ ]tc /bin"
insert_at_position "$test_line" "[ ]" 7 actual
assert_equals "test_insert_cursor_char-p7 failed" "$expected" "$actual"
test_line = "/etc /bin"
expected = "/tmp /etc /bin"
insert_at_position "$test_line" "/tmp " 0 actual
assert_equals "test_insert_cursor_char-p0 failed" "$expected" "$actual"
test_line = "/etc /bin"
expected = "/tmp"
insert_at_position "$test_line" "/tmp " 0 actual
assert_equals "test_insert_cursor_char - here fail is expected" "$expected" "$actual"
}
test_insert_at_position
Просто нарежьте строку var следующим образом:
str='abcd'
ins='O_o'
$ echo ${str:0:2} ${str:2}
ab cd
$ echo ${str:0:2}$ins${str:2}
abO_ocd
В этом решении «$string» и «$index_position» необходимо указать дважды. Я больше предпочитаю подход с функциями для уменьшения дублирования кода. Его проще использовать и проще поддерживать.