Как я могу использовать сценарий оболочки, чтобы заменить имя файла с содержимым этого файла - PullRequest
0 голосов
/ 21 апреля 2020

Скажем, у меня есть файл, который включает в себя произвольное количество других имен файлов (в распознаваемых разделителях), например,

original-file-contents-which-should-remain
{{filename.txt}}
more-untouchable-contents
{{dir/myfile.md}}

Как использовать сценарий оболочки для замены имен файлов (и разделителей), то есть , {{filename.txt}} и {{dir/myfile.md}} с содержимым соответствующих файлов?

Я пытался использовать sed, и хотя он работает, если я жестко закодировал имя целевого файла, он не может получить имя файла из регулярного выражения - ie, следующее удаляет {{myfile}}, но не вводит содержимое ./myfile (наверное, захват регулярных выражений работает только с командами s/old/new):

sed -e "/{{\(.*\)}}/ { r \1" -e "d}" somefile

Ответы [ 3 ]

4 голосов
/ 21 апреля 2020

Если у вас есть GNU sed, то вы можете использовать флаг e для команды s следующим образом:

sed -f - input_file <<'EOS'
    s/^\s*{{\([^']*\)}}\s*$/cat '\1'/e
EOS

Сначала заменяется шаблон, содержащий имя файла. с помощью команды оболочки cat filename команда запускается, и ее вывод передается обратно в пространство шаблонов.

Как вы можете видеть, программа sed загружается из литерала здесь-do c вместо обычная строка в одинарных кавычках, поскольку она позволяет использовать одинарные кавычки для включения имени файла в команду оболочки, сохраняя чистоту всей команды sed (и если вы не полностью доверяете содержимому ваших входных файлов, одинарные кавычки безопаснее, чем двойные кавычки) , В целях безопасности снова регулярное выражение адреса предотвращает использование одинарных кавычек в имени файла и использует оба начала / конца якоря строки, чтобы гарантировать, что команда оболочки не загрязнена возможными начальными / конечными частями.

Как указано KamilCuk Вы также можете использовать GNU awk. Он поставляется с библиотекой дополнительных функций, таких как readfile, и здесь неплохо бы избегать использования команды оболочки.

gawk -i readfile '
    ! match($0, /^\s*\{\{(.*)}}\s*$/, refs) { print ; next }
    { printf "%s", readfile(refs[1]) }
' input_file

(обновлено для возможных пробелов вокруг шаблонов и ненужного экранирования благодаря портативный ответ от Эда Мортона )

2 голосов
/ 21 апреля 2020

Это будет работать с любым awk в любой оболочке на каждом поле UNIX с учетом ввода, как в вашем примере:

awk '
match($0,/\{\{.*}}/) {
    fname = substr($0,RSTART+2,RLENGTH-4)
    while ( (getline < fname) > 0 ) {
        print
    }
    close(fname)
    next
}
{ print }
' file

например,

$ cat tam
When chapman billies leave the street,
And drouthy neebors neebors meet,
As market-days are wearing late,
{{foo}}
We think na on the lang Scots miles,
The mosses, waters, slaps, and stiles,
{{bar}}
Gathering her brows like gathering storm,
Nursing her wrath to keep it warm.

$ cat foo
And folk begin to tak the gate;
While we sit bousin, at the nappy,
And gettin fou and unco happy,

$ cat bar
That lie between us and our hame,
Whare sits our sulky, sullen dame,

.

awk '
match($0,/\{\{.*}}/) {
    fname = substr($0,RSTART+2,RLENGTH-4)
    while ( (getline < fname) > 0 ) {
        print
    }
    close(fname)
    next
}
{ print }
' tam
When chapman billies leave the street,
And drouthy neebors neebors meet,
As market-days are wearing late,
And folk begin to tak the gate;
While we sit bousin, at the nappy,
And gettin fou and unco happy,
We think na on the lang Scots miles,
The mosses, waters, slaps, and stiles,
That lie between us and our hame,
Whare sits our sulky, sullen dame,
Gathering her brows like gathering storm,
Nursing her wrath to keep it warm.

Образец ввода любезно предоставлен Рабб ie Ожоги .

1 голос
/ 21 апреля 2020

Использование vim версии ex:

ex -c 'g/{{/s/{{\([^}]*\)}}/\=readfile(submatch(1))/g' -c 'x!' input.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...