3

Я хочу вставить текст в середине файла. Текст для вставки будет после определенной строки, скажем, « <begin> ». Я не знаю номер строки и не знаю, сколько строк в тексте нужно вставить. Я только знаю, что после строки, которая гласит « <begin> », мне нужно вставить содержимое другого файла.

Я просто не знаю, как использовать awk, чтобы сделать что-то подобное.

Спасибо :-)

3 ответа3

5
/<begin>/{
    insert_file("before_file.html")
    print $0
    insert_file("after_file.html")
    next
}
{
    print $0
}

где вам придется написать функцию insert_file которая может выглядеть примерно так:

function insert_file(file) {
    while (getline line <file)
        print line
    close(file)
}

Обратите внимание, что эта точная версия не работает должным образом на моем Mac, когда before_file и after_file совпадают ...Я получаю только первый экземпляр. Вероятно, это связано с невозможностью закрыть файл. Я буду расследовать. Да, необходимо close файл, и это следует сделать в целом для хорошей практики.


Кроме того, я думаю, что это может быть даже проще в sed ...

Для вставки файла после ключевой строки

sed '/<begin>/r after_file.html' input_file

Вставить файл раньше немного сложнее,

 sed -n -e '/^function/r before_file.html' -e 'x' -e 'p' input_file

так что вы можете использовать скрипт как

/^function/r before_file.html
x
p

с

sed -n -f script input_file
2

Perl - старший брат в awk.

perl -p -i -e 'print "some text\n" if /<begin>/' filename

Если у вас есть несколько <begin>, то это нужно будет изменить.

РЕДАКТИРОВАТЬ: О, вы хотели вставить файл

perl -MFile::Slurp -p -i -e 'print read_file("file2") if /<begin>/' filename

(проверено нормально, но сначала вам может понадобиться cpan File::Slurp .)

1

Создайте файл со следующим кодом. Вы можете сохранить его как:
insertfile.awk (или что угодно)

    BEGIN{
        while ( (getline < outerfile) > 0 )
        {
            if ($0 == matchline) 
            {  
                if ("after" == includematch)
                {
                    print
                }
                if ("before" == includematch)
                {
                    holdline = $0
                }
                  while ( (getline < innerfile) > 0) 
                {
                    print
                }
                close(innerfile)
                if ("before" == includematch)
                {
                     print holdline
                     holdline = ""
                }
            }
            else
            {
                print
            }
        }
        close(outerfile)
    }

Используемые параметры командной строки awk:

-v outerfile="file1.txt"    This is the name of the file you are searching (and printing).
-v innerfile="file2.txt"    This is the name of the file you will insert when you file a match
-v matchline="Search Text"  This is what you will search for as a line in file1.txt
-v includematch="before"    Optional: insert the file, before the matchline
-v includematch="after"     Optional: insert the file, after the matchline
-v includematch=""          If "includematch" is any other value, or empty, or not present, 
                            then insert the file, REPLACING matchline.
-f "insertfile.awk"         This is the name of the awk command file.

Затем, чтобы использовать его, вы вызываете awk следующим образом:

awk -v outerfile="file1.txt" -v innerfile="file2.txt" -v matchline="cat" -f "insertfile.awk"  
(Read and print "file1.txt".  Search for line containing only "cat". REPLACE "cat" lines with "file2.txt"  

awk -v outerfile="file1.txt" -v innerfile="file2.txt" -v matchline="dog" -v includematch="before" -f "insertfile.awk"
(Read and print "file1.txt".  Search for line containing only "dog". Insert "file2.txt" Before matched line.

awk -v outerfile="file1.txt" -v innerfile="file2.txt" -v matchline="bird" -v includematch="after" -f "insertfile.awk"
(Read and print "file1.txt".  Search for line containing only "bird". Insert "file2.txt" After matched line.

В скрипте awk вы можете редактировать его так:

Change $0 to $1 or $2 or other to match a specific word instead of the whole line.  
"hard-code" the file-names instead of outerfile and innerfile if you wish.

Если вы хотите "передать" входные данные в сценарий вместо того, чтобы получать их из файла, отредактируйте сценарий insertfile.awk следующим образом:

        {
            if ($0 == matchline) 
            {

                if ("after" == includematch)
                {
                    print
                }
                if ("before" == includematch)
                {
                    holdline = $0
                }

                while ( (getline < innerfile) > 0) 
                {
                    print
                }
                close(innerfile)

                if ("before" == includematch)
                {
                     print holdline
                     holdline = ""
                }

            }
            else
            {
                print
            }
            close(outerfile)
        }

Затем, чтобы использовать его, вы вызываете awk следующим образом:

type "somefile.txt" | awk -v innerfile="file2.txt" -v matchline="cat" -f "insertfile.awk"  
(Read and print STDIN.  Search for line containing only "cat". REPLACE "cat" lines with "file2.txt"  

type "anyfile.txt" | awk -v innerfile="file2.txt" -v matchline="dog" -v includematch="before" -f "insertfile.awk"
(Read and print STDIN.  Search for line containg only "dog". Insert "file2.txt" Before matched line.

type "otherfile.txt" | awk -v innerfile="file2.txt" -v matchline="bird" -v includematch="after" -f "insertfile.awk"
(Read and print STDIN.  Search for line containg only "bird". Insert "file2.txt" After matched line.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .