Заменить определенный токен содержимым файла (используя bash-скрипт) - PullRequest
5 голосов
/ 07 декабря 2010

У меня есть файл, содержащий текст и слова INSERT_HERE1 и INSERT_HERE2.Я хотел бы заменить эти слова содержимым file1.txt и file2.txt соответственно.

Я подозреваю, что sed или awk могли бы справиться с этим, но я в принципе никогда не использовал их.

Ответы [ 7 ]

8 голосов
/ 27 июня 2012

Sed имеет встроенную команду чтения файла. Команды, которые вы хотите, будут выглядеть примерно так:

$ sed -e '/INSERT_HERE1/ {
r FILE1
d }' -e '/INSERT_HERE2/ {
r FILE2
d }' < file

Это выдаст

foo
this is file1
bar
this is file2
baz

Команда r читает файл, а команда d удаляет строку с тегами INSERT_HERE. Вы должны использовать фигурные скобки, так как команды sed и многострочный ввод должны начинаться с собственной строки, и в зависимости от вашей оболочки вам может понадобиться \ в конце строк, чтобы избежать преждевременного выполнения. Если это то, что вы часто используете, вы можете просто поместить команду в файл и использовать sed -f для ее запуска.

4 голосов
/ 07 декабря 2010

Если вы в порядке с Perl, вы можете сделать:

$ cat FILE1
this is file1

$ cat FILE2
this is file2

$ cat file
foo
INSERT_HERE1
bar
INSERT_HERE2
baz

$ perl -ne 's/^INSERT_HERE(\d+)\s+$/`cat FILE$1`/e;print' file
foo
this is file1
bar
this is file2
baz
$ 
1 голос
/ 25 июня 2016

Я бы использовал замену perl вместо -i.ext option

perl -pi.bak -e 's|INSERT_HERE1|`cat FILE1`|ge; 
                 s|INSERT_HERE2|`cat FILE2`|ge;' myfile

Затем используйте diff myfile.bak myfile для проверки:

1 голос
/ 16 апреля 2013

Этот фрагмент заменяет любой раздел, указанный в верхнем массиве. Например, здесь

<!--insert.txt-->

с содержимым "insert.txt"

#!/bin/bash

replace[1]=\<!--insert.txt--\>      ; file[1]=insert.txt
replace[2]=\<!--insert2.txt--\>     ; file[2]=insert2.txt

replacelength=${#replace[@]}

cat blank.txt > tmp.txt
for i in $(seq 1 ${replacelength})
do
    echo Replacing ${file[i]} ...
    sed -e "/${replace[i]}/r ${file[i]}" -e "/${replace[i]}/d" tmp.txt > tmp_2.txt
    mv tmp_2.txt tmp.txt
done
mv tmp.txt file.txt

Если вы не боитесь ZIP-файлов, вы можете попробовать этот пример, пока он находится в сети: http://ablage.stabentheiner.de/2013-04-16_contentreplace.zip

1 голос
/ 08 декабря 2010

Легко делается с помощью Bash. Если вам нужна оболочка POSIX, дайте мне знать:

#!/bin/bash

IFS=  # Needed to prevent the shell from interpreting the newlines
f1=$(< /path/to/file1.txt)
f2=$(< /path/to/file2.txt)

while read line; do 
  if [[ "$line" == "INSERT_HERE1" ]]; then
     echo "$f1"
  elif [[ "$line" == "INSERT_HERE2" ]]; then
     echo "$f2"
  else
     echo "$line"
  fi
done < /path/to/input/file
1 голос
/ 08 декабря 2010

Это подходит для небольших файлов подстановки, которые могут быть заменены много раз:

awk 'BEGIN {
        while ((getline line < ARGV[1]) > 0) {file1 = file1 nl line; nl = "\n"}; 
        close (ARGV[1]); nl = "";
        while ((getline line < ARGV[2]) > 0) {file2 = file2 nl line; nl = "\n"};
        close (ARGV[2]);
        ARGV[1] = ""; ARGV[2] = "" }
      { gsub("token1", file1); 
        gsub("token2", file2); 
        print }' file1.txt file2.txt mainfile.txt

Возможно, вы захотите добавить дополнительные строки в зависимости от того, как вы хотите, чтобы ваш вывод выглядел.*

1 голос
/ 07 декабря 2010

Это не проверено, но будет достаточно близко к тому, что вам нужно:

sed -e "s/INSERT_HERE1/`cat file1.txt`/" -e "s/INSERT_HERE2/`cat file2.txt`/" <file >file.out

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

Однако я бы порекомендовал Perl.Примерно так:

#!/usr/bin/perl -w

my $f1 = `cat file1.txt`;
my $f2 = `cat file2.txt`;

while (<>) {
    chomp;
    s/INSERT_HERE1/$f1/;
    s/INSERT_HERE2/$f2/;
    print "$_\n";
}

Предполагается, что INSERT_HERE1 и INSERT_HERE2 могут появляться только один раз на строку, и что file1.txt не включает в себя текст INSERT_HERE2 (хотя это не трудно исправить).Используйте как это:

./script <file >file.out
...