Предположив, что картина в вашей команде grep
идентифицирует все строки, которые должны быть изменены и никаких других строки, вы могли бы написать sed
команды, которая соответствует той же схеме, и подставляется значение атрибута value
на нем:
sed '/MetaDatum key="Pr" value="VALUE/ s/value="[^"]*"/value="VALUE"/' $f
Заметим, однако, что такой подход (как grep
и sed
) очень чувствительны к точным деталям вашего XML. Он будет падать на разное количество пробелов, чем вы ожидаете - особенно встроенные новые строки - на дополнительные атрибуты, на разные варианты котировок и т. Д.
Некоторые из них могут быть решены более умными шаблонами, а другие нет. Чтобы правильно обрабатывать XML, вам нужны надежные инструменты XML. В этом случае подходящим инструментом будет преобразование XSLT. Вот преобразование, которое будет выполнять работу (при условии, что исходный файл не переопределены по умолчанию XML пространство имен - спасибо, CharlesDuffy):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- identity transform: anything not otherwise matched is copied verbatim -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--
-- Transform the 'value' attribute of MetaDatum elements where the
-- element has a 'key' attribute with value 'Pr', and the 'value'
-- attribute's own value starts with 'VALUE'.
-->
<xsl:template match="MetaDatum[@key = 'Pr']/@value[substring(., 1, 5) = 'VALUE']">
<xsl:attribute name="value">VALUE</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Вы можете применять его через любой XSLT процессор, но один из наиболее распространенных из них xsltproc
, который поставляется с libxslt от GNOME. Если преобразование хранится в файле meta.xsl
, то команды, чтобы заменить файл $f
с преобразованным выходом через xsltproc
может быть:
temp=`mktemp` && xsltproc meta.xsl "$f" > "$temp" && mv "$temp" "$f"
Как @CharlesDuffy отмечен в комментариях, что может привести к файлу с именем по $f
, имеющим разным права собственности и/или более ограничительные разрешения, чем это было ранее. Как вы можете решить эту проблему, зависит от доступных инструментов. Например, хотя стандартные chown
и chmod
не имеют его, версии GNU имеют механизмы для настройки права собственности и разрешений файла в соответствии с файлами другого файла. Кроме того, вам нужно подумать о том, какое желаемое поведение относится к случаю, когда $f
называет символическую ссылку (замените ссылку или измените файл, на который она указывает). Поскольку эти вопросы, зависящие от среды и предпочтения, если команда, представленная выше, не обрабатывает их по своему усмотрению, тогда вам нужно будет решить, как пересмотреть подход.
Если вам нужно иметь дело с переопределенным пространством имен XML по умолчанию, тогда шаблон должен быть немного сложнее. Вам нужно будет объявить префикс пространства имен для пространства имен элемента MetaDatum
и его атрибутов и использовать его везде, где вы ссылаетесь на эти имена.
Насколько большая часть этой строки уникальна для строк, которые вы хотите отредактировать? Достаточно ли '
@EtanReisner: 'grep -l' возвращает файлы. – choroba
Да, спасибо, забыли '-l'. Остальной части вашего q: '