Как извлечь текстовые разделы в отдельные файлы, названные на основе идентификатора? - PullRequest
0 голосов
/ 18 мая 2019

Учитывая текстовый файл, содержащий серии повторяющихся текстовых разделов, как мне следует извлечь эти разделы и сохранить их в отдельных текстовых файлах, имя которых происходит от идентификатора каждого раздела?

  • Все разделы начинаютсяс <?xml и оканчивается на </svg>.
  • У всех разделов есть тег id, который должен служить основой для их имени.

Я не уверен, как два sed REGEXesдля достижения этой цели потребуется объединить в for loop.


Original.svg:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="France" width="1500" height="1000" viewBox="0 0 3 2">
<rect width="3" height="2" fill="#009246"/>
<rect width="2" height="2" x="1" fill="#fff"/>
<rect width="1" height="2" x="2" fill="#ce2b37"/>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Italy" width="900" height="600">
<rect width="900" height="600" fill="#ED2939"/>
<rect width="600" height="600" fill="#fff"/>
<rect width="300" height="600" fill="#002395"/>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Ireland" width="1200" height="600">
<rect fill="#169b62" width="1200" height="600" />
<rect fill="#fff" x="400" width="800" height="600" />
<rect fill="#ff883e" x="800" width="400" height="600" />
</svg>

Результат:

France.svg:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="France" width="1500" height="1000" viewBox="0 0 3 2">
<rect width="3" height="2" fill="#009246"/>
<rect width="2" height="2" x="1" fill="#fff"/>
<rect width="1" height="2" x="2" fill="#ce2b37"/>
</svg>

Italy.svg:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Italy" width="900" height="600">
<rect width="900" height="600" fill="#ED2939"/>
<rect width="600" height="600" fill="#fff"/>
<rect width="300" height="600" fill="#002395"/>
</svg>

Ireland.svg:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Ireland" width="1200" height="600">
<rect fill="#169b62" width="1200" height="600" />
<rect fill="#fff" x="400" width="800" height="600" />
<rect fill="#ff883e" x="800" width="400" height="600" />
</svg>

Ответы [ 4 ]

1 голос
/ 19 мая 2019

Благодаря GNU awk для мультисимвольного RS для разделения файлов на допустимый XML для каждого раздела SVG, выполняется совместная обработка, позволяющая печатать записи в xmlstarlet и считывать вывод, второй аргумент - close(), позволяющий нам закрыть канал в xmlstarlet, чтобы он обрабатывал ввод, и xmlstarlet для фактического чтения XML:

$ cat ../tst.awk
BEGIN {
    RS  = "</svg>[[:space:]]*"
    ORS = ""
    xmlParser = "xmlstarlet select -N x=\047http://www.w3.org/2000/svg\047 --template --value-of \047//x:svg/@id\047"
}
RT != "" {
    $0 = $0 RT

    print |& xmlParser
    close(xmlParser,"to")

    if ( (xmlParser |& getline id) > 0 ) {
        print > (id ".svg")
    }
    close(xmlParser)
}

Например, где file содержит вводимый текст вопроса:

$ ls
file  tst.awk

$ awk -f tst.awk file

$ ls
file  tst.awk  France.svg  Ireland.svg  Italy.svg

$ tail -n +1 *.svg
==> France.svg <==
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="France" width="1500" height="1000" viewBox="0 0 3 2">
<rect width="3" height="2" fill="#009246"/>
<rect width="2" height="2" x="1" fill="#fff"/>
<rect width="1" height="2" x="2" fill="#ce2b37"/>
</svg>

==> Ireland.svg <==
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Ireland" width="1200" height="600">
<rect fill="#169b62" width="1200" height="600" />
<rect fill="#fff" x="400" width="800" height="600" />
<rect fill="#ff883e" x="800" width="400" height="600" />
</svg>

==> Italy.svg <==
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Italy" width="900" height="600">
<rect width="900" height="600" fill="#ED2939"/>
<rect width="600" height="600" fill="#fff"/>
<rect width="300" height="600" fill="#002395"/>
</svg>

Сбой, если бы </svg> был внутри комментария или строки и, возможно, других контекстов, которых у вас, похоже, нет. idk, что вы хотите сделать, если в разделе XML нет id, поэтому я просто не распечатываю XML, если это произойдет.

1 голос
/ 19 мая 2019

С bash и xmlstarlet:

#!/bin/bash

while read -r line; do

  # fill variable with all lines and append newline to every line
  svg="$svg$line"$'\n'

  # last line?
  if [[ $line =~ \</svg\> ]]; then

    # extract attribute from xml
    svgfile=$(xmlstarlet select -N x='http://www.w3.org/2000/svg' --template --value-of '//x:svg/@id' <<< "$svg")

    # remove trailing newline and output xml to new file
    echo -e "${svg:0:-1}" > "${svgfile}.svg"

    unset svg
  fi
done < Original.svg
0 голосов
/ 18 мая 2019

Вот скрипт consice awk, выполняющий ваш запрос. Предполагая, что есть согласованная структура файла из 6 строк.

script.awk

{++line; lines = lines"\n"$0;}
NR%6 == 2 {id = substr($3, 5, length($3)-5)".svg"; next;}
NR%6 == 0 {
        print lines > id;
        line = 0; lines = "";
}

команда запуска

awk -f script.awk Original.svg

Если вам нужен запрос объяснения в комментариях.

0 голосов
/ 18 мая 2019

Вот хрупкое, но портативное решение awk.

awk '
            {a[i++]=$0}
  /^<svg/   {for(f=1; f<=NF; f++) if($f~/^id=/) split($f, id, /["=]+/)}
  /^<\/svg/ {for(n=0; n<i; n++) print a[n] > (id[2] ".svg"); i=0}
' Original.svg
  1. Поместите каждую строку в массив, проиндексированный с шагом
  2. В строках, начинающихся с <svg, разбейте третье полев массив id, используя один или несколько символов равенства или двойных кавычек.
  3. В строках, начинающихся с </svg, выполняйте итерацию по массиву, печатая каждый элемент (строку) в файл с именем, объединяя второй результатнаш сплит id[2] с расширением файла ".svg".

Пожалуйста, рассмотрите возможность голосования и выберите этот ответ, если он вам помог.Я отвечу на любые вопросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...