Как заменить список заполнителей в текстовом файле?

Для единственного файла вместо того, чтобы использовать SFTP Вы могли передать файл по каналу по использованию ssh cat или pv в передающей стороне и использовании tee на среднем сервере, чтобы и отправить данные в файл туда и отправить копию по другому ssh связывают другую сторону, которой просто пишет данные в файл. Точный вуду потребовал, чтобы я уехал как осуществление в читателя, поскольку я не добрался, время для проигрывания прямо сейчас (извините). Этот метод только работал бы, если второе место назначения публично доступно через SSH, который не может иметь место, поскольку Вы описываете его как клиентскую машину.

Другой подход, который меньше "выполняется и ожидает", но может иначе быть легче, это для использования rsync между сервером и клиентом B. В первый раз, когда Вы выполняете это, это может получить частичную копию данных, но можно просто повторно выполнить его для получения большего количества данных впоследствии (с одним финалом, выполненным однажды Client1->, передача Сервера завершена). Это будет только работать, если сервер поместит данные, прямые в правильное имя файла во время передачи SFTP (иногда, то Вы будете видеть, что данные входят во временный файл, который затем переименован, после того как файл полностью передается - это сделано, чтобы заставить файл обновить более атомарный, но представит rsync неприменимую идею). Вы могли также использовать rsync для C1-> S передача вместо scp (если Вы используете --inplace опция избежать проблемы упомянула выше) - использующий rsync, также дал бы Вам защиту от необходимости снова послать все, если C1-> Серверное соединение испытывает проблемы во время большой передачи (я склонен использовать rsync --inplace -a --progress <source> <dest> вместо scp/sftp, когда rsync доступен для этого "поведения" резюме передачи).

Суммировать вышеупомянутое, работая:

rsync --inplace -a --progress <source> user@server:/<destination_file_or_folder>

на client1, затем работающем

rsync --inplace -a --progress user@server:/<destination_file_or_folder> <destination_on_cli2>

на client2 неоднократно, пока первая передача не завершена (затем работающий еще раз, чтобы удостовериться, что у Вас есть все). rsync очень хорошо только в передаче абсолютного минимума, это должно обновить местоположение вместо того, чтобы передать всех каждый раз. Для паранойи Вы могли бы хотеть добавить --checksum опция к командам rsync (который займет намного больше процессорного времени для больших файлов, но не приведет к значительно большему количеству данных, переданных, если это не будет необходимо), и для скорости --compress опция поможет, если данные, которые Вы передаете, уже не будут в сжатом формате.

5
02.09.2011, 13:51
5 ответов

Я, вероятно, записал бы некоторый сценарий для расширения переменных оболочки для генерации выходного файла конфигурации.

Вот некоторые подсказки:

  1. здесь-строки (<<<) расширены
  2. можно загрузить переменные ". varaibles.conf"
  3. env -i script.sh запустит скрипт в чистой среде (никакие дополнительные переменные)

Таким образом, сценарий должен будет создать новый временный сценарий, который получит переменные и здесь-строку кошки с расширенным Варом. Затем для получения окончательного результата необходимо будет запустить тот временный сгенерированный скрипт через env -i.

3
27.01.2020, 20:39

@fred имеет что-то вроде верной мысли, но намного более простая система могла бы быть:

sed -ne '/^#/d;s!^\([^=]*\)=\(.*\)$!s@\1@\2g!p' my.proprties > script.sed
sed -f script.sed my.conf | target_prog

Это также только генерирует для строк, которые имеют "PROP=VALUE", и игнорирует строки комментария.

Выламывание этого:

/^#/d                   - delete any comment lines (to ignore #PROP=VALUE)
s!^\([^=]*\)=\(.*\)$    - match any line with PROP=VALUE and place PROG into group 1 and VALUE into group 2
!s@\1@\2@g              - replace with s@GROUP1@GROUP2@g
!p                      - print the line, to override the -n

Вы заканчиваете с sed сходством со сценария:

s@PROP1@VALUE1@g
s@PROP2@VALUE2@g
...
2
27.01.2020, 20:39
  • 1
    хорошая идея (+1).. FWIW, я склонен использовать \x01 в качестве разделителя sed wnen, данные неизвестны. –  Peter.O 03.09.2011, 08:32

Существует два препроцессора, которые могут утверждать, что были традиционными препроцессорами Unix: cpp (препроцессор C) и m4. Ни один не является подходящим к общей предварительной обработке, потому что они заменяют слова где угодно в тексте, и в случае cpp налагают синтаксис комментария. Разумный общий препроцессор имел бы макро-индикатор (т.е. не разворачивайте каждое возникновение name, расширьтесь только @name (например)).

Нет никакого препроцессора, что я рассмотрел бы фактический стандарт или даже просто распространенный. Один это адаптировано ко множеству форматов ввода, и доступный на многих дистрибутивах Linux GPP.

Если Вы хотите придерживаться стандартных инструментов, можно использовать оболочку в качестве препроцессора при некоторых обстоятельствах. Создайте строку, затем работайте

eval 'preprocessed=$(cat <<EOF)
$template
EOF'

Параметры Shell и команды ($var, $(command), `command`) будет расширен. Обратите внимание, что Вы не можете легко препятствовать тому, чтобы шаблон вызвал внешние команды или присвоил переменным, используемым сценарием, не используйте это, если Вы не доверяете месту, куда шаблон прибывает из.

1
27.01.2020, 20:39

Вероятно, самым широко распространенным и портативным путем к простому макрорасширению является препроцессор C:

cat my.properties my.conf | cpp -P -DSOME_DIR=/a/b -DOTHER_DIR=/c | target_prog

Обратите внимание, что необходимо использовать cat здесь, как cpp только принимает входной файл того как параметр.

Но поскольку Вы записали, что у Вас есть много переменных, можно предпочесть помещать их в файл:

#define SOME_DIR /a/b
#define OTHER_DIR /c

Затем передайте его cpp как:

cat my.properties my.conf | cpp -P -imacros definition.cpp | target_prog
0
27.01.2020, 20:39
  • 1
    препроцессор C очень плохо адаптирован к общей предварительной обработке. Это налагает синтаксис комментария C и переписывает все слова, которые объявляются как макросы. Для общей предварительной обработки, имея символ макрорасширения хорошая идея. –  Gilles 'SO- stop being evil' 03.09.2011, 01:29

Обновление: расширение Arcegeидея sed-to-sed, у Вас может быть более managable расположение (табличный, или неровный) для Ваших шаблонов find/repl, которые могут быть встроены... и нет никакой потребности в промежуточном файле: (добавьте a g перед p'<<'EOF' вносить несколько изменений на строку... Отметьте это foo, barbar, и т.д. будут рассматривать sed как регулярные выражения.

I=$'\01'; sed -nre "s/^([^ ]+) +/s$I\1$I/;s/$/$I/p"<<'EOF' |sed -f - file
foo           By the middle of June,
barbar        mosquitos were rampant,
foofoofoo     the grass was tawny, a brown dust
barbarbarbar  haze hung over the valley
EOF

(исходное сообщение)
Можно использовать sed как исполняемый сценарий, с оберткой...

Можно определить находку и заменить текст в отдельном текстовом файле,
но для этого образца это определяется встроенное...

Этот сценарий преобразовывает Ваших find/repl пар в sed выражения и динамично создает исполняемый сценарий

I=$'\01'; set -f
printf "#!/bin/sed -f\n" > ~/bin/script.sed
while IFS= read -r line ;do
    ix=$(expr index "$line" " ")
    printf "s%s%s%s%s%s\n" $I ""${line:0:$((ix-1))}"" $I "${line:$ix}" $I 
done <<'EOF' >> ~/bin/script.sed
$text1 By the middle of June,
$text2 mosquitos were rampant,
$text3 the grass was tawny, a brown dust
$text4 haze hung over the valley
EOF
chmod +x ~/bin/script.sed

Это - тестовый файл, который будет изменен.
'$' хорошо, поскольку это не в конце строки (для sed), и это никогда не будет выставлено оболочке, но любому маркеру, который не столкнется с sed прекрасен. Можно даже использовать #

echo '$text1 $text2 $text3 $text4' > file  

Принятие этого ~/bin каталог $PATH, команда для выполнения:

script.sed  file   
0
27.01.2020, 20:39

Теги

Похожие вопросы