/ / Parse xml za pomocą narzędzi powłoki, takich jak grep, awk lub sed [duplicate] - bash, shell, awk, sed

Przetestuj xml za pomocą narzędzi powłoki, takich jak grep, awk lub sed [duplicate] - bash, shell, awk, sed

Mam następujący xml do parsowania i rozpakowywaniawartość tagu na podstawie wartości tagu. Wyodrębnij tylko wtedy, gdy typ == "hostowany". Chciałbym wyodrębnić za pomocą narzędzi bash, takich jak grep, sed i awk. Wyodrębnianie wartości pojedynczego tagu bez warunku jest czymś, co zrobiłem wcześniej, a nie warunkami. Mogę łatwo zrobić to za pomocą pythona lub dowolnego innego języka programowania, jaki znam. Ale byłoby to idealne, gdyby zostało zrobione w skrypcie powłoki.

...
<repositories-item>
<name>hosted-npm</name>
<type>hosted</type>
</repositories-item>
<repositories-item>
<name>proxied-npm</name>
<type>proxied</type>
</repositories-item>
...

Odpowiedzi:

3 dla odpowiedzi № 1

xmlstarlet jest zestawem narzędzi XML do wiersza poleceń, który może wyrażać złożone szablony XSLT jako krótką sekwencję przełączników linii poleceń.

Załóżmy, że mamy do dyspozycji dobrze sformułowany dokument XML repos.xml

<repositories>
<repositories-item>
<name>hosted-npm</name>
<type>hosted</type>
</repositories-item>
<repositories-item>
<name>proxied-npm</name>
<type>proxied</type>
</repositories-item>
</repositories>

Jeśli uruchomisz go za pomocą filtra XMLStarlet z następującymi przełącznikami

$ cat repos.xml | xmlstarlet sel -t -m "//repositories-item" 
-i "type="hosted"" -v "name" -n

Otrzymasz jedną linię danych wyjściowych

hosted-npm

Spójrzmy na wiersz poleceń XMLStarlet.

  1. Uruchomimy polecenie w trybie Select określonym za pomocą sel przełącznik
  2. Określamy szablon wyboru z -t przełącznik
  3. Ograniczamy parser do <repositories-item> elementy z //repositories-item szablon określony za pomocą -m swicth
  4. Wybieramy tylko te elementy, które "hostowane" jako wartość type element określony za pomocą -i przełącznik
  5. Drukujemy wartość name element, określony przez -v przełącznik.
  6. Po każdym wierszu wyjścia drukujemy znak nowej linii określony przez -n przełącznik.

Oto odpowiednik XSLT generowanego przez XMLStarlet

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
<xsl:output omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
<xsl:for-each select="//repositories-item">
<xsl:choose>
<xsl:when test="type=&quot;hosted&quot;">
<xsl:call-template name="value-of-template">
<xsl:with-param name="select" select="name"/>
</xsl:call-template>
<xsl:value-of select=""&#10;""/>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template name="value-of-template">
<xsl:param name="select"/>
<xsl:value-of select="$select"/>
<xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
<xsl:value-of select=""&#10;""/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Zgodnie z sugestią Charlesa Duffy'ego warto zauważyć, że ta specyfikacja XSLT może zostać wygenerowana za pomocą XMLStarlet przy użyciu -C opcja:

xmlstarlet sel -C -t -m "//repositories-item" 
-i "type="hosted"" -v "name" -n > hosted-repos.xslt

Ta wygenerowana specyfikacja XSLT może być bezpośrednio używana z xsltproc tak jak

cat repos.xml | xsltproc hosted-repos.xslt -

0 dla odpowiedzi nr 2

brakuje narzędzi specyficznych dla xml

awk na ratunek przy użyciu znaczników otaczających, aby zdefiniować ograniczniki rekordów

$ awk -v RS="</?repositories-item>" "/<type>hosted</type>/" file

<name>hosted-npm</name>
<type>hosted</type>

Zauważ, że wymaga to wielu znaków RS, które GNU awk obsługuje.

możesz mieć większą kontrolę nad dopasowaniem i wyjściem

$ awk -v RS="</?repositories-item>" -F"[<>]" "
{delete a;
for(i=2;i<=NF;i+=4) a[$i]=$(i+1);
if(a["type"]=="hosted") print a["name"] }" file


hosted-npm