2

У меня есть файлы следующей структуры:

foo.bar.baz () ->
  templateUrl: require('x.jade')

Мне нужно преобразовать эти файлы так, чтобы:

  1. Они имеют префикс строки var templateUrl = require('x.jade')
  2. Строка templateUrl: заменяется на templateUrl: templateUrl .

Как я могу это сделать? Одним из вариантов является bash-скрипт, который для каждого файла:

  1. grep s для templateUrl: получить require часть.
  2. cat объединяет строку var templateUrl и файл в новый файл, а затем заменяет исходный файл.
  3. Использует sed для замены templateUrl: require... на templateUrl .

Но можно ли это сделать с помощью одного сценария sed или awk который можно выполнить для каждого файла?

2 ответа2

2

Входной файл (ы):

foo.bar.baz () ->
  templateUrl: require('x.jade')

команда perl :

perl -i -0777pe '$_=~s/templateUrl:( \K.*)/templateUrl/;print"var templateUrl =$1\n"' *

Выходные файлы:

var templateUrl = require('x.jade')
foo.bar.baz () ->
  templateUrl: templateUrl

Сломать:

  • язык сценариев perl , превосходящий текстовые манипуляции
  • -i редактировать файлы на месте
  • -0777 работать с файлом в целом, а не построчно
  • p распечатать файл (в этом случае файл будет сохранен благодаря -i)
  • e выполнить следующую команду, в отличие от исполняемого кода , который сохраняется в файле
  • ' инструкции
  • $_=~s выполняет подстановку всего файла ( $_)
  • /templateUrl:( \K.*))/ искать строку, соответствующую регулярному выражению templateUrl: .* , и записать строку, соответствующую подвыражению в скобках  .* в переменную (по умолчанию она называется $1)
  • templateUrl/ заменить деталь после маркера \K в совпавшей строке с текстом templateUrl
  • ; отделяет инструкции
  • print"var templateUrl =$1\n" печать var templateUrl = , содержимое $1 и символ новой строки
  • на этом этапе остальная часть файла печатается неявно, потому что был указан переключатель p
  • ' инструкций
  • * обрабатывать каждый файл в текущем каталоге

Конечно, могут быть разные подходы, такие как:

perl -i -ne 'if ($_=~s/templateUrl:( \K.*)/templateUrl/){$a="templateUrl =$1"} {$file.=$_} END{print"var $a\n$file"}' *

AWK:
Поскольку вопрос касается sed или awk , стоит отметить, что любой из этих подходов может быть легко реализован в awk:

awk -i 'BEGIN {RS="\0"} {match($0,/templateUrl:( .*)/,m); gsub("templateUrl: .*","templateUrl: templateUrl"); print "var templateUrl ="m[1]$0}' *
awk -i '/templateUrl: / {a="templateUrl = "$2;gsub("templateUrl: .*","templateUrl: templateUrl")} NR==1 {file=$0} NR==2{file=file"\n"$0} END{print a"\n"file}' *
2

perl решение @ simlev действительно имеет меньше шагов, но я бы хотел представить свою команду sed . Это более актуально, потому что OP уже предусмотрел использование sed и явно запрашивает скрипт sed или awk .

sed -n '1h;:a;n;s/require/&/;tInsert;H;ba;:Insert;H;s/^/var/;s/:/ =/;G;s/: .*/: templateUrl/;p'

Примечание. Эта команда не будет работать, если файл содержит более одной строки с : или require .

Объяснение:

sed -n        # -n option disables automatic printing.

1 h           # h command puts the first line (address 1) in the hold space,
              # replacing any previous content.

:a            # Set a mark with label 'a'.

n             # n command prints the pattern space and loads next line of input,
              # replacing all pattern space content.
              # But it will not print because of -n option.

s/require/&/  # Test if the pattern space has the line OP wants edit.

t Insert      # If substitution was made, t command jumps to the mark with label 'Insert'.

H             # If not, continue with H command, it appends a '\n' to the hold space content
              # and then appends the pattern space to the hold space.

b a           # b (branch) command, jumps to the mark with label 'a'.

:Insert       # Exit from the 'a' loop. Here the hold space has all the lines that precede
              # the line with 'replace', and pattern space has the line with 'replace'.
H             # The line with 'replace' is appended to the hold space too.

s/^/var/      # Here sed finally edits the line, replacing the beginning with 'var' ...

s/:/ =/       # and only the first ':' with ' ='.

G             # G command appends the content of hold space to the edited pattern space,
              # here that line edited above in pattern space becomes the first line.

s/: .*/: templateUrl/    # One more substitution.

p'            # Finally, print the pattern space.

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