2017-06-08 3 views
0

Ich habe eine XML-Datei aus mehreren Blöcken, die sehr ähnlich sind. Hier sind zwei:Tauschen Sie zwei Blöcke von Text programmatisch

<Grid Name="EMFieldMany" GridType="Uniform"> 
     <Topology TopologyType="3DRectMesh" Dimensions="40 40 40 "/> 
     <Attribute AttributeType="Scalar" Name="Er" Center="Node"> 
      <DataItem Dimensions="40 40 40 " NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/field/Er-0 
      </DataItem> 
     </Attribute> 
     <Geometry GeometryType="VXVYVZ"> 
      <DataItem Name="r" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/r 
      </DataItem> 
      <DataItem Name="theta" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/theta 
      </DataItem> 
      <DataItem Name="z" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/z 
      </DataItem> 
     </Geometry> 
    </Grid> 
    <Grid Name="EMFieldMany" GridType="Uniform"> 
     <Topology TopologyType="3DRectMesh" Dimensions="40 40 40 "/> 
     <Attribute AttributeType="Scalar" Name="Er" Center="Node"> 
      <DataItem Dimensions="40 40 40 " NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/field/Er-1 
      </DataItem> 
     </Attribute> 
     <Geometry GeometryType="VXVYVZ"> 
      <DataItem Name="r" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/r 
      </DataItem> 
      <DataItem Name="theta" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/theta 
      </DataItem> 
      <DataItem Name="z" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/z 
      </DataItem> 
     </Geometry> 
    </Grid> 

Typischerweise ich Hunderte von ähnlichen <Grid> Objekte in einer einzigen Datei. Nun möchte ich programmatisch die Positionen der und <DataItem Name="z"> Blöcke in jedem <Grid> Objekt austauschen, so dass die <DataItem> s in der Reihenfolge z, Theta, r sind. Für jede Dimensions=" x y z "-Anweisung, jedes Dimensions-Attribut, das drei Werte enthält, möchte ich, dass das Attribut als Dimensions=" z y x " umgeschrieben wird.

Ich habe nicht wirklich etwas dagegen, die Programmiersprache verwendet wird, um dies zu tun. Ich bin auf einer Linux-Workstation mit Bash, Python, Perl ... all den Standard-Sachen.

EDIT: Diese answer verwendet sed, um Blöcke von Text, aber ich bin mir nicht sicher, wie Sie den ausgewählten Block danach manipulieren. Diese other answer vertauscht einzelne Zeilen nach oben und unten, aber ich bin mir nicht sicher, wie man Textblöcke verallgemeinern und Blöcke vertauschen soll.

+0

Können Sie nach, was Sie bisher versucht haben? – Tbaki

+0

Sicher. Ich habe meine Frage aktualisiert. Ich bin mir nicht sicher, wie man Textblöcke mit "sed" manipulieren kann oder ob es einfach ist. –

+0

Verwenden Sie geeignete XML-orientierte Tools. Versuchen Sie nicht, es mit String-Ersatz zu tun, es wird Sie früher oder später beißen. –

Antwort

1

Wie Sie sed erwähnen, schlage ich vor, Diese Perl-Lösung, aber es ist besser, XML mit Xml-Parser zu analysieren.

#!/usr/bin/perl 

# changing input line separator 
$/="</Grid>"; 

while ($_=<>) { 
    [email protected](\s*<DataItem Name="r".*?</DataItem>)(\s*<DataItem Name="theta".*?</DataItem>)(\s*<DataItem Name="z".*?</DataItem>)@[email protected]; 
    [email protected]<DataItem Dimensions="\K(\d+) (\d+) (\d+) @$3 $2 $1 @; 
    print; 
} 

Oder die Einzeiler Äquivalent

perl -pe 'BEGIN{$/="</Grid>"}[email protected](\s*<DataItem Name="r".*?</DataItem>)(\s*<DataItem Name="theta".*?</DataItem>)(\s*<DataItem Name="z".*?</DataItem>)@[email protected];[email protected]<DataItem Dimensions="\K(\d+) (\d+) (\d+) @$3 $2 $1 @;' <input.txt 
+0

Diese Syntax ist so einfach! Ich denke, ich werde etwas Perl lernen müssen! –

0

Sie tun können, ersetzen Sie sie durch, wenn Sie Ihre XML als String haben:

#Swapping ('\"' the slash escape the " to make it the string caracter) 
XML_str = XML_str.replace("\"r","SomethingThatNeverAppearInTheXML") 
XML_str = XML_str.replace("\"z","\r") 
XML_str = XML_str.replace("SomethingThatNeverAppearInTheXML","\"z") 
#Replacing 
XML_str = XML_str.replace("x y z","z y x") 

Eingang

XML_str = """  
    <Grid Name="EMFieldMany" GridType="Uniform"> 
     <Topology TopologyType="3DRectMesh" Dimensions="40 40 40 "/> 
     <Attribute AttributeType="Scalar" Name="Er" Center="Node"> 
      <DataItem Dimensions="40 40 40 " NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/field/Er-0 
      </DataItem> 
     </Attribute> 
     <Geometry GeometryType="VXVYVZ"> 
      <DataItem Name="r" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/r 
      </DataItem> 
      <DataItem Name="theta" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/theta 
      </DataItem> 
      <DataItem Name="z" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/z 
      </DataItem> 
     </Geometry> 
    </Grid> 
    <Grid Name="EMFieldMany" GridType="Uniform"> 
     <Topology TopologyType="3DRectMesh" Dimensions="40 40 40 "/> 
     <Attribute AttributeType="Scalar" Name="Er" Center="Node"> 
      <DataItem Dimensions="40 40 40 " NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/field/Er-1 
      </DataItem> 
     </Attribute> 
     <Geometry GeometryType="VXVYVZ"> 
      <DataItem Name="r" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/r 
      </DataItem> 
      <DataItem Name="theta" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/theta 
      </DataItem> 
      <DataItem Name="z" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
       Field_reflected_time_3D.hdf5:/coordinates/z 
      </DataItem> 
     </Geometry> 
    </Grid> 
""" 

Ausgang

<Grid Name="EMFieldMany" GridType="Uniform"> 
    <Topology TopologyType="3DRectMesh" Dimensions="40 40 40 "/> 
    <Attribute AttributeType="Scalar" Name="Er" Center="Node"> 
     <DataItem Dimensions="40 40 40 " NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
      Field_reflected_time_3D.hdf5:/field/Er-0 
     </DataItem> 
    </Attribute> 
    <Geometry GeometryType="VXVYVZ"> 
     <DataItem Name="z" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
      Field_reflected_time_3D.hdf5:/coordinates/r 
     </DataItem> 
     <DataItem Name="theta" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
      Field_reflected_time_3D.hdf5:/coordinates/theta 
     </DataItem> 
     <DataItem Name="r" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
      Field_reflected_time_3D.hdf5:/coordinates/z 
     </DataItem> 
    </Geometry> 
</Grid> 
<Grid Name="EMFieldMany" GridType="Uniform"> 
    <Topology TopologyType="3DRectMesh" Dimensions="40 40 40 "/> 
    <Attribute AttributeType="Scalar" Name="Er" Center="Node"> 
     <DataItem Dimensions="40 40 40 " NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
      Field_reflected_time_3D.hdf5:/field/Er-1 
     </DataItem> 
    </Attribute> 
    <Geometry GeometryType="VXVYVZ"> 
     <DataItem Name="z" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
      Field_reflected_time_3D.hdf5:/coordinates/r 
     </DataItem> 
     <DataItem Name="theta" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
      Field_reflected_time_3D.hdf5:/coordinates/theta 
     </DataItem> 
     <DataItem Name="r" Dimensions="40" NumberType="Float" Precision="8" Format="HDF5" Endian="Big"> 
      Field_reflected_time_3D.hdf5:/coordinates/z 
     </DataItem> 
    </Geometry> 
</Grid> 
+0

Welche Sprache oder Shell ist das? – Jack

+0

Es ist Python, ich habe ein Problem mit der Muster-Definition, aber gütet dort. – Tbaki

+0

@Jack Das sollte funktionieren – Tbaki

1

Dies kann leicht mit ed erfolgen:

g/<DataItem Name="r"/-ka\ 
/<DataItem Name="z"/\ 
-kb\ 
.,/\/DataItem/m'a\ 
+1,/\/DataItem/m'b 
Verwandte Themen