Замена сегментов в нескольких строках другим сегментом в том же файле, который находится в нескольких папках, с помощью find и sed

У меня есть следующая структура каталогов из нескольких папок:

Applications
|
|____Salford_123
|   |_________SomeFile.png
|   |_________AnotherFile.nui
|   |_________MenuSettings.txt
|   |_________Data
|             |_____Settings.txt
|
|____Salford_546
|   |_________SomeFile.png
|   |_________AnotherFile.nui
|   |_________MenuSettings.txt
|   |_________Data
|             |_____Settings.txt
|
|____Salford_789
|   |_________SomeFile.png
|   |_________AnotherFile.nui
|   |_________MenuSettings.txt
|   |_________Data
|             |_____Settings.txt

Текстовый файл MenuSettings.txt в каждой папке со следующим содержимым:

AppName: "http://www.bbc.co.uk”
DoubleWidthTile: "False"
TileColor: "0.76 0 0.24 1"
AnimationSize: "10 10"
AppName_xx_XX: “Venice Quays”
AppName_yy_YY: “Venice Quays”

Этот файл и его родительская папка создаются автоматически несколько раз. Первая строка файла имеет каждый раз другой URL-адрес, который может быть любой длины. Я пытаюсь скопировать сегмент с URL-адресом, чтобы заменить значения в AppName_xx_XX: и AppName_yy_YY: чтобы он выглядел так

AppName: "http://www.bbc.co.uk”
DoubleWidthTile: "False"
TileColor: "0.76 0 0.24 1"
AnimationSize: "10 10"
AppName_xx_XX: “http://www.bbc.co.uk”
AppName_yy_YY: “http://www.bbc.co.uk”

В записях для AppName_xx_XX: и AppName_yy_YY: будет сгенерировано любое слово любой длины с пробелами и знаками препинания. Часть строки xx и yy может состоять из двух любых символов. Поэтому я использовал «найти» для рекурсивного поиска по папкам и команду «sed» для копирования и замены сегментов, которые выводятся в другой файл, который я затем mv -v возвращал к оригиналу.

find salford* -maxdepth 1 -type d \( ! -name . \) -exec sh -c '(cd {} && 

cat MenuSettings.txt | sed -e 's/AppName\_en\_[[A-Z]]\:[[:blank:]]\"[[:alpha:]]*.\"/AppName\:[[:space:]]\"[[:alpha:]]*.[[:alpha:]]*.[[:alpha:]]*.\"/g' > MenuSettings3.txt

)' ';'

Файл bash запускается без ошибок, но не работает, так как сгенерированный файл не показывает никаких изменений. Где я ошибаюсь?


person Eggfoot    schedule 04.02.2016    source источник


Ответы (1)


$ sed '/^AppName: */{h;s///;x;}; /^\(AppName_.._..:\).*/{s//\1/;G;s/\n/ /;}' MenuSettings.txt
AppName: "http://www.bbc.co.uk”
DoubleWidthTile: "False"
TileColor: "0.76 0 0.24 1"
AnimationSize: "10 10"
AppName_xx_XX: "http://www.bbc.co.uk”
AppName_yy_YY: "http://www.bbc.co.uk”

Я работал с вашим описанием, чтобы сделать приведенную выше команду sed. Я использую буфер удержания для сохранения URL-адреса и для строк xx/yy, добавляемых из буфера удержания после избавления от исходного значения.

Первое выражение в квадратных скобках использует задержку для создания копии строки в буфере заморозки. s/// повторно использует последний шаблон и ничем его не заменяет, оставляя только URL-адрес в кавычках. x заменяет отредактированную строку на копию, поэтому выводит исходную строку, сохраняя URL-адрес в буфере хранения.

Следующее выражение в квадратных скобках использует s//\1/ для повторного использования последнего шаблона и замены совпадения захваченными символами. G добавляет содержимое буфера хранения в конец пространства шаблона после новой строки. s/\n/ / заменяет новую строку пробелом.

person dan4thewin    schedule 04.02.2016
comment
Спасибо за этот @dancancode, использование удержания в sed — это то, чего я не осознавал до сих пор. Можно ли удерживать сегмент между файлами? - person Eggfoot; 04.02.2016
comment
sed обрабатывает несколько файловых аргументов как поток ввода. Буфер удержания находится в памяти, поэтому, когда sed завершает работу, буфер удержания исчезает (если только вы не запишете его в файл с помощью команды w). Если вы передаете несколько файлов одной команде sed (и вы не используете переключатель -i на месте), значение в буфере удержания может использоваться с входными данными из последующих файлов. - person dan4thewin; 04.02.2016