С ограниченным набором входных файлов, которыми вы управляете содержимым, вы можете использовать awk
или аналогичный метод, чтобы заменить source
команду в потоке stdin исходным файлом. Например,
desource <local-script.sh | ssh user@remote
где desource это скрипт
#!/bin/sh
awk '$1=="source" && NF>=2 {
file = $2; while((getline <file)>0)print $0
close(file); next
}
{ print }' "$@"
Это просто совпадает со строками, первое слово которых является "источником" и принимает второе слово в качестве файла для вставки. getline
читает строку из этого файла (в $ 0) и возвращает 0 в конце файла. Строка print
просто копирует несоответствующие строки.
Очевидно, что это сильно ограничено в его применении, и, например, потребуется некоторая работа для повторения, если во включенном файле также есть source
команды.
альтернативный getline с переменной вместо $ 0:
while((getline inp <file)>0)print inp
альтернативный скрипт с использованием sed
. Он читает файл дважды, поэтому для использования требуется имя файла ( опустите «<», то есть: desource local-script.sh | ssh user@remote
)
#!/bin/bash
file=${1?}
cmd=$( sed -n '/^[ \t]*source[ \t]/{=;s///;p}' <$file |
sed '/^[0-9]/{N;s/\n\(.*\)/{r \1;d;}/}' |
tr ';' '\012' )
sed "$cmd" <$file
Это использует sed первый раз, чтобы соответствовать source
строкам, распечатать номер строки (=) и оставить только имя файла (s/// повторно использует тот же шаблон).
2nd sed берет номер строки, добавляет следующую строку (N) и заменяет новую строку и следующее имя файла (. * - остаток строки) на то, что станет командой sed для чтения требуемого файла и удаления исходной строки. tr
преобразует точки с запятой в команде в новые строки. Полученная команда передается третьему седу в исходном файле.