Bash - поиск определенной строки в файле и ее замена непосредственным источником - PullRequest
0 голосов
/ 20 сентября 2018

Я пытаюсь найти строку «отсутствует» в файле, содержащем следующее:

<message>
    <source>TypeA</source>
    <translation>missing</translation>
</message>
<message>
    <source>TypeB</source>
    <translation>missing</translation>
</message>
<message>
    <source>TypeC</source>
    <comment>Context menu</comment>
    <translation>missing</translation>
</message>

И если «отсутствует», я хочу заменить строку ее непосредственным именем источника,Например, это:

<message>
    <source>TypeA</source>
    <translation>TypeA</translation>
</message>
<message>
    <source>TypeB</source>
    <translation>TypeB</translation>
</message>
<message>
    <source>TypeC</source>
    <comment>Context menu</comment>
    <translation>TypeC</translation>
</message>

Я смог использовать awk для поиска строки и распечатать непосредственное имя источника:

match($0, /<source>(.*)<\/source>/,n){ src=n[1] }
match($0, /<translation>(.*)<\/translation>/,s){ trs=s[1] }
/unfinished/{ print "Translation missing or incomplete for: '" trs "'","located inside source named: '" src "'" }

И затем сохранить его как something.awk.это с помощью:

awk -f something.awk filelocation

Но я не уверен, как заменить строку «отсутствует» значением из источника.

Может кто-нибудь подсказать, как мне его заменить?

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Даже если вы приняли ответ, я бы добавил его.

В своем комментарии вы сказали нам, что ваш входной файл является правильно сформированным XML-документом.Так что я бы справился с этим XML-способом.Мне нравится awk / sed / grep, однако я должен сказать, что они (и regex) на самом деле не являются подходящими инструментами для обработки XML-файлов, хотя иногда он работает быстро и грязно.

Существует инструмент командной строки: xsltproc, что может преобразовать xml-документ в другой формат с помощью xslt.

xslt также относительно прост: (сохраните его как f.xslt)

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="translation[.='missing']">
        <xsl:copy>
            <xsl:value-of select="../source"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

что вам нужно сделать, этопросто:

xsltproc f.xslt input.xml

Протестируйте немного с вашим входным файлом: ( Я добавил один корневой элемент )

kent$  cat f.xml
<root>
        <message>
                <source>TypeA</source>
                <translation>missing</translation>
        </message>
        <message>
                <source>TypeB</source>
                <translation>missing</translation>
        </message>
        <message>
                <source>TypeC</source>
                <comment>Context menu</comment>
                <translation>missing</translation>
        </message>
</root>

kent$  xsltproc f.xslt f.xml
<?xml version="1.0"?>
<root>
        <message>
                <source>TypeA</source>
                <translation>TypeA</translation>
        </message>
        <message>
                <source>TypeB</source>
                <translation>TypeB</translation>
        </message>
        <message>
                <source>TypeC</source>
                <comment>Context menu</comment>
                <translation>TypeC</translation>
        </message>
</root>

Это всегда будет работать, покаВаш ввод XML хорошо сформирован.Это нормально, даже если ваш ввод XML в одной строке или в другом формате.

0 голосов
/ 20 сентября 2018

Вы можете использовать свой вывод в качестве переменной и передать его в sed для замены, по моему мнению, простота делает его идеальным,

sed s/'$AWK_RESULT/"REPALACE_STATE"/g'

вы сможете использовать его внутри цикла во время итерации вашегодырочный текст.

0 голосов
/ 20 сентября 2018

Вы можете попробовать это (напишите это в нечто .awk):

{
    if($0 ~ "<source>"){
            source = gensub(/.*<source>(.*)<\/source>.*/, "\\1", "", $0)
    }
    if($0 ~ "<translation>missing"){
            $0 = gensub(/>.*</, ">" source "<", "", $0)
    }
     print
}

Я не знаю, нужна ли вам конкретная версия awk для использования gensub ... (может быть, gawk?).Но он работает на моем компьютере, когда я:

awk -f something.awk filelocation

Результат:

<message>
    <source>TypeA</source>
    <translation>TypeA</translation>
</message>
<message>
    <source>TypeB</source>
    <translation>TypeB</translation>
</message>
<message>
    <source>TypeC</source>
    <comment>Context menu</comment>
    <translation>TypeC</translation>
</message>

Как я уже сказал, это может быть серьезной проблемой, если порядок тегов не соблюдается (или еслиу вас есть несколько тегов на строку, ...).Это не имеет большого значения, если у вас есть тег между источником и переводом, но источник должен быть перед переводом.Если это не так, вам может потребоваться проанализировать ваш файл с помощью правильного инструмента синтаксического анализа XML (awk iks't), внести изменения и распечатать в файл.

...