Использование sed с переменной подстановки, которая может иметь фигурные скобки - PullRequest
0 голосов
/ 28 мая 2020

Я пишу сценарий для перебора набора файлов в каталоге, ищущего строку (stringA) в одном файле (srcFile), копирую следующую за ней строку (stringToCopy) и вставка его в строку после другой строки поиска (stringB) в другом файле (outputFile). Скрипт копирования / вставки, который у меня есть, выглядит следующим образом:

stringA="This is string A"
stringB="This is string B"
srcFile=srcFile.txt
outpuFile=outputFile.txt
replacement="/$stringA/{getline; print}"
stringToCopy="$(awk "$replacement" $srcFile)"
sed -i "/$stringB/!b;n;c${stringToCopy}" $outputFile

Скрипт отлично работает, за исключением случаев, когда stringToCopy заканчивается фигурными скобками. Пример:

srcFile.txt:

This is string A
text to copy: {0}

outputFile.txt:

This is string B
line to be replaced

После того, как скрипт будет готов, я ожидаю, что outputFile.txt будет

This is string B
text to copy: {0}

Но sed задыхается от

sed: -e expression #1, char 106: unknown command: `m'

Я пробовал жестко кодировать строку с проблемойati c и пробовать различные варианты экранирования завитушек и цитирования строки, но не нашел выигрышная комбинация, и я не понимаю, как заставить ее работать.

EDIT У меня был сумасшедший момент, и я забыл, что мой stringA также имеет фигурные скобки, из-за которых моя команда awk вычисляла несколько строк. Это привело к тому, что в моем stringToCopy были символы новой строки, что является моей настоящей проблемой, а не фигурными скобками. Итак, реальный вопрос заключается в том, как заставить awk обрабатывать фигурные скобки как буквальные символы, чтобы srcFile.txt

This is string A: {0}
text to copy: {0}

This is string A:
Other junk

и stringA="This is string A: {0}"

не устанавливал stringToCopy в

text to copy: {0}
Other junk

1 Ответ

1 голос
/ 28 мая 2020

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

Текущая ситуация:

$ awk '/This is string A: {0}/{getline; print}' srcFile.txt
text to copy: {0}                   # this is the line we want
Other junk                          # we do not want this line

Мы можем удалить вторую строку, экранирование фигурных скобок в шаблоне поиска, например:

$ awk '/This is string A: \{0\}/{getline; print}' srcFile.txt
text to copy: {0}

Итак, как избежать фигурных скобок? Мы можем использовать некоторые явные расширения параметров, чтобы заменить фигурные скобки на экранированные фигурные скобки в переменной $stringA, имея в виду, что нам также необходимо экранировать фигурные скобки на этапе раскрытия параметра:

$ stringA="This is string A: {0}"
$ stringA="${stringA//\{/\\{}"      # replace '{' with '\{'
$ stringA="${stringA//\}/\\}}"      # replace '}' with '\}'
$ echo "${stringA}"
This is string A: \{0\}

Мы затем можно продолжить с остальной частью кода как есть:

$ replacement="/$stringA/{getline; print}"
$ echo "${replacement}"
/This is string A: \{0\}/{getline; print}

$ stringToCopy="$(awk "$replacement" $srcFile)"
$ echo "${stringToCopy}"
text to copy: {0}

Что касается последнего шага sed, мне пришлось удалить !, чтобы он работал правильно:

$ sed -i "/$stringB/b;n;c${stringToCopy}" $outputFile
$ cat "${outputFile}"
This is string B
text to copy: {0}

ПРИМЕЧАНИЯ :

  • если вы начнете кодирование с помощью set -xv, вы сможете увидеть, как переменные интерпретируются на каждом шаге; используйте set +xv, чтобы выключить
  • , очевидно, вы, вероятно, столкнетесь с проблемами, если у вас действительно есть более 1 совпадающей строки в $srcFile
  • , если вы найдете другие символы, которые необходимо быть экранированным, вам нужно будет добавить дополнительные расширения параметров для указанных символов
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...