Получить список имен файлов с разделителями из текстового файла - PullRequest
2 голосов
/ 30 июня 2009

Я действительно новичок в Bash, так что это может показаться глупым для большинства из вас. Я пытаюсь получить список некоторых имен файлов из текстового файла. Пытался сделать это с помощью sed и awk, но не смог заставить его работать с моими ограниченными знаниями.

Это пример содержимого файла:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 13.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 width="471.677px" height="126.604px" viewBox="0 0 471.677 126.604" enable-background="new 0 0 471.677 126.604"
 xml:space="preserve">
<rect x="0.01" y="1.27" fill="none" width="471.667" height="125.333"/>
<text transform="matrix(1 0 0 1 0.0098 8.3701)"><tspan x="0" y="0" font-family="'MyriadPro-Regular'" font-size="10">/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf</tspan><tspan x="0" y="12" font-family="'MyriadPro-Regular'" font-size="10">/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf</tspan><tspan x="0" y="24" font-family="'MyriadPro-Regular'" font-size="10">/Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf</tspan></text>
</svg>

Я хотел бы получить из этого примера новый текстовый файл с таким точным содержанием:

/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf /Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf /Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf

Я подумал сказать sed распечатать все соответствующие записи между 'font-size"10">' и '</tspan>', но ... лучшее, что я получил, был файл со всей строкой, содержащей мои разделители полей.

Если бы вы могли объяснить каждый сделанный шаг, было бы здорово.

  • Имена файлов могут быть более или менее. Это 3 только пример.

Ответы [ 6 ]

1 голос
/ 30 июня 2009

Как насчет этого:

cat file.xml | sed -e's/^[^>]*>//' -e's/<.*$//' | grep \\.

Это не очень общего назначения, но быть полностью общим было бы ОЧЕНЬ сложнее (для XML требуется полный анализатор и т. Д.).

По сути, скрипт sed состоит из двух частей. Сначала удалите все символы от начала строки (^) до первого символа «>». Обратите внимание, что я сопоставляю все не ">", чтобы сделать это. Вторая часть удаляет все символы от самого левого символа «<» до конца строки. Поскольку эта вторая часть появляется ПОСЛЕ первой части, она выполняется после завершения первой зачистки, поэтому она не стирает всю строку. </p>

Тогда оператор grep возвращает только строки с "." в них только строки с именами файлов.

Надеюсь, это поможет!

0 голосов
/ 12 декабря 2009
awk 'BEGIN{RS="font-size=\"10\">|</tspan>"}/pdf/' xml.txt

Результат

$ awk 'BEGIN{RS="font-size=\"10\">|"}/pdf/' xml.txt
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf

Этот код, вероятно, самый простой, но без грязного регулярного выражения, и его очень легко расширить и легко настроить по своему вкусу. Я решил сопоставить с термином «pdf» отсюда и часть кода /pdf/, но если, например, у вас есть другие файлы, которые вы хотите сопоставить, которые не являются файлами PDF, но содержат слово «Тома», вы можете просто используйте /Volumes/ вместо.

0 голосов
/ 01 июля 2009

Если у вас есть xmlgawk, вы можете легко получить.

@load xml

BEGIN {
    XMLMODE = 1;
    XMLCHARSET = "utf-8";
}

XMLCHARDATA {
    data = $0;
}

XMLENDELEM == "tspan" {
    print data;
}

и

$ xgawk -f pick_from_svg.awk sample.xml 
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf
0 голосов
/ 30 июня 2009

Другие дали хорошие ответы о том, почему вы должны использовать правильный синтаксический анализатор XML, если вы хотите обойти синтаксический анализ XML, но в качестве объяснения того, как сделать это в sed, на случай, если вы столкнетесь с подобной проблемой: 1001 *

#Full Command
sed -n 's/^[^<]*<tspan[^>]*>\([^<]*\)<.*/\1/p'  ~/your_file.xml 

Параметр n запрещает отправке sed никаких выходных данных, если об этом не попросили Обычно sed повторяет пробел в конце, что может сбить с толку

Начиная с s, так как [s] заменял. Знак "/", который следует, говорит sed, что мы будем использовать "/" для разделения различных частей скрипта.

Возьмите все с начала строки (^) вместе со всем, что после этого не является открытой скобкой ([^ `<] *). Это будет отброшено позже. </p>

Возьмите tspan и все, что после него, которое не является закрывающей скобкой ([^>] *>). Это также будет отброшено.

Возьмите все после этой закрывающей скобки, это не открытая скобка. Это часть, которую мы хотим сохранить, поэтому мы заключаем ее в экранированные скобки. "([^ <] *)" </p>

Захватите все от последней закрывающей скобки до конца строки "<. *". Мы тоже это выбросим. </p>

Вторая часть команды: \ 1 Все это означает: повторите все, что было в первом наборе экранированных скобок, которые мы использовали ранее. Был только один набор скобок, поэтому \ 2, \ 3 и т. Д. Здесь не имеют смысла, но вы можете использовать их в других скриптах. В вашем случае вы хотите повторить то, что мы нашли внутри вашего

Наконец: «p» заставляет sed распечатывать спички. В начале это работает с -n, что означает «ничего не печатать», кроме «совпадений»

Надеюсь, это было полезно ...

0 голосов
/ 30 июня 2009

Sed и awk, как правило, не являются правильным способом чтения XML. Они могут работать, но XML может изменить макет в любое время и сломать вещи, оставаясь при этом совершенно корректным XML.

Намного лучше использовать что-то вроде Perl. Установите модуль XML :: Smart либо через CPAN, либо в ubunto с помощью команды "sudo apt-get install libxml-smart-perl".

Тогда простой скрипт, подобный этому:

use strict;
use diagnostics;

use XML::Smart;

my $xml = XML::Smart->new ("svg.xml") || die "Cannot read XML: $!.";
my $version = $xml->{svg}{version} || die "Cannot determine SVG version.";

foreach my $file ($xml->{svg}{text}{tspan}('@')) {
    print $file->content . "\n";
}

Сохранить как svg.pl. Сохраните ваш XML как svg.xml.

$ perl svg.pl / Volumes / Secondary500 / Temp / Untitled-2_Layer 1 copy 2.pdf / Volumes / Secondary500 / Temp / Untitled-2_Layer 1 copy.pdf / Volumes / Secondary500 / Temp / Untitled-2_Layer 1.pdf

Это:

  • Анализирует XML, проверяя его правильность.
  • Проверяет, существует ли версия (на самом деле это просто проверка работоспособности).
  • Перебирает массив всех svg / text / tspans и печатает содержимое.

Веселись!

0 голосов
/ 30 июня 2009

Команда sed для этого будет

 sed  -n 's|font-size="[0-9]*".\(.*\)</tspan.*|\1|p' file.xml
            -------------------  --  ---------
               prefix part       \1   suffix

Вот как это работает,

  • -n подавляет печать всех строк из буфера
  • p в конце указывает, что замененный буфер должен быть напечатан
  • '|', используемый в качестве разделителя вместо обычного '/', помогает легко фильтровать разделители путей
  • строка поиска совпадает для всего контента между font-size="[0-9]*". и `
  • нас интересует часть между \( и \)
    • \1 указывает, что мы хотим сохранить это в буфере для печати

В этой команде используется оператор группы , который описан здесь .

В вашем файле это дает,

/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy 2.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1 copy.pdf
/Volumes/Secondary500/Temp/Untitled-2_Layer 1.pdf

Обратите внимание, что важно получить правильный префикс и строки суффикса, чтобы получить все совпадения. В вашем примере это части font-size и tspan, которые я нашел выше. Но, это может быть не так со всеми строками файла в вашем файле. Так что проверь это.

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