
Я хотел бы добавить несколько строк после совпавшей строки в текстовом файле в скрипте bash. Хотя мне не особо важно, какой инструмент выбрать для этой работы, для меня важно то, что я хочу указать строки, добавленные "как есть" внутри скрипта (то есть без создания дополнительного файла, который бы их хранил), чтобы они попали в переменную Bash, и без необходимости цитировать/экранировать что-либо в них - и для этой цели мне подойдет использование heredoc с кавычками. Вот пример appendtest.sh
:
cat > mytestfile.txt <<'EOF'
"'iceberg'"
"'ice cliff'"
"'ice field'"
"'inlet'"
"'island'"
"'islet'"
"'isthmus'"
EOF
IFS='' read -r -d '' REPLACER <<'EOF'
"'$oasis$'"
"'$ocean$'"
"'$oceanic trench$'"
EOF
echo "$REPLACER"
sed -i "/ \"'ice field'\"/a${REPLACER}" mytestfile.txt
К сожалению, это не работает:
$ bash appendtest.sh
"'$oasis$'"
"'$ocean$'"
"'$oceanic trench$'"
sed: -e expression #1, char 39: unknown command: `"'
... потому что sed
не удалось, когда использовалась неэкранированная многострочная замена. Поэтому мой вопрос:
- Что я мог бы использовать вместо этого
sed
для сопоставления строк текста и вставки/добавления строк, как указано в переменной Bash ($REPLACER
в примере)?
решение1
Если вы используете GNU sed
, лучшим вариантом будет использовать r
команду:
sed -i "/ \"'ice field'\"/ r /dev/stdin" mytestfile.txt <<'EOF'
"'$oasis$'"
"'$ocean$'"
"'$oceanic trench$'"
EOF
решение2
Хорошо, нашел один способ с помощью perl
:
cat > mytestfile.txt <<'EOF'
"'iceberg'"
"'ice cliff'"
"'ice field'"
"'inlet'"
"'island'"
"'islet'"
"'isthmus'"
EOF
IFS='' read -r -d '' REPLACER <<'EOF'
"'$oasis$'"
"'$ocean$'"
"'$oceanic trench$'"
EOF
# echo "$REPLACER"
IFS='' read -r -d '' LOOKFOR <<'EOF'
"'ice field'"
EOF
export REPLACER # so perl can access it via $ENV
# -pi will replace in-place but not print to stdout; -p will only print to stdout:
perl -pi -e "s/($LOOKFOR)/"'$1$ENV{"REPLACER"}'"/" mytestfile.txt
# also, with export LOOKFOR, this works:
# perl -pi -e 's/($ENV{"LOOKFOR"})/$1$ENV{"REPLACER"}/' mytestfile.txt
cat mytestfile.txt # see if the replacement is done
Вывод такой, как и хотелось бы:
$ bash appendtest.sh
"'iceberg'"
"'ice cliff'"
"'ice field'"
"'$oasis$'"
"'$ocean$'"
"'$oceanic trench$'"
"'inlet'"
"'island'"
"'islet'"
"'isthmus'"