Как я могу получить из списка с несколькими строками одно имя файла?

В вашей проблеме есть 3 элемента:

  • построение "списка исключений" - обратите внимание, что "специальные" символы в вашем списке исключений могут вызвать проблемы.
  • чтение вашего файла, исключая строку, если она 'совпадает'.
  • запись вашего нового файла.

В вашем вопросе - думаю, есть пара вещей, которые я бы назвал "плохим стилем".

  • лексические дескрипторы файлов с 3 открытыми аргументами - это хороший стиль.
  • вызов системы для запуска perl изнутри perl неэффективен.
  • интерполяция кавычек - это неудобство, которого лучше всего избежать
  • повторной обработки выходного файла, что ужасно неэффективно. (Помните - дисковый IO - это самая медленная вещь, которую вы будете делать в вашей системе).

Так что, имея это в виду - вот как я это сделаю:

#!/usr/bin/env perl
use strict;
use warnings;

my $infile = "remove.txt";
open( my $pattern_fh, '<', $infile ) or die "cannot open $infile $!";

#quotemeta escapes meta characters that'll break your pattern matching. 
my $regex = join( '|', map {quotemeta} <$pattern_fh> );
#compile the regex
$regex = qr/^($regex)$/;    #whole lines
close($input_fh);

print "Using regular expression: $regex\n"; 

open( my $input_fh,  '<', "foo" )     or die $!;
open( my $output_fh, '>', "foo.new" ) or die $!;

#tell print where to print by default. 
#could instead print {$output_fh} $_; 
select($output_fh);
while (<$input_fh>) {
    print unless m/$regex/;
}
close($input_fh);
close($output_fh);

#rename/copy if it worked

(NB: Не тестировался исчерпывающе - если вы сможете привести примеры данных, я буду тестировать/обновлять по мере необходимости)

.
1
02.04.2018, 22:12
3 ответа

Грубая сила.

Если ваш проанализированный xml находится вbooks

while read a; read b; read c; read d; read e; do wget $c -O $b$e$d$a; echo $c; done < books

Просто перекомпонуйте свои строки как переменные, и все готово, пока ваши блоки записей заполнены до 5 строк.

0
27.01.2020, 23:32

If what I'm doing is not best practice, I'm open to other methods.

Я предлагаю вам не использовать bashили sedи т. д.! И используйте путь python, который, безусловно, намного лучше для анализа xml, который вам нужно проанализировать. Я только что написал и протестировал это с помощью python3.6, и он делает именно то, что вы просили.

#!/usr/bin/python3
# Let's import the modules we need
import wget
import os
import requests
from bs4 import BeautifulSoup as bs

# Assign the url to a variable (not essential as we 
# only use it once, but it's pythonic)
url = 'https://librivox.org/api/feed/audiobooks/?offset=0&limit=3&fields=%7Blanguage,authors,title,url_zip_file%7B'

# Use requests to fetch the raw xml
r = requests.get(url)

# Use BeautifulSoup and lxml to parse the raw xml so 
# we can do stuff with it
s = bs(r.text, 'lxml')

# We need to find the data we need. This will find it and create some 
# python lists for us to loop through later

# Find all xml tags named 'url_zip_file' and assign them to variable
links = s.find_all('url_zip_file')

# Find all xml tags named 'last_name' and assign them to variable
last_names = s.find_all('last_name')

# Find all xml tags named 'last_name' and assign them to variable
first_names = s.find_all('first_name')

# Find all xml tags named 'language' and assign them to variable
language = s.find_all('language')

# Assign the language to a variable
english = language[0].text

# Make our new language directory
os.mkdir(english)

# cd into our new language directory
os.chdir(str(english))

# Loop through the last names (ln), first names(fn) and links
# so we can make the directories, download the file, rename the 
# file then we go back a directory and loop again
for ln, fn, link in zip(last_names, first_names, links):
    os.mkdir('Author{}{}'.format(str(ln.text), str(fn.text)))
    os.chdir('Author{}{}'.format(ln.text, fn.text))
    filename = wget.download(link.text)
    os.rename(filename, 'File.zip')
    os.chdir('../')

Вы можете либо сохранить это в файл, либо просто вставить/впечатать в cli интерпретатора python3, решать вам.

Вам нужно будет установить python3 -wget и beautifulsoup4 с помощью pip или простой _установки и т. д.

1
27.01.2020, 23:32

Если вы можете использовать jq, Librivox API также предоставляет выходные данные JSON, и, возможно, будет проще анализировать JSON с помощью jq, чем XML с помощью соответствующих инструментов XML.

u='https://librivox.org/api/feed/audiobooks/?offset=0&limit=3&fields=%7Blanguage,authors,title,url_zip_file%7B&format=json'
curl "$u" -sL |
  jq -r '.books[] | "\(.language).\(.authors[0].last_name +.authors[0].first_name).\(.title).zip",.url_zip_file'

Дает вывод, подобный:

English.DumasAlexandre.Count of Monte Cristo.zip
http://www.archive.org/download/count_monte_cristo_0711_librivox/count_monte_cristo_0711_librivox_64kb_mp3.zip
English.BalzacHonoré de.Letters of Two Brides.zip
http://www.archive.org/download/letters_brides_0709_librivox/letters_brides_0709_librivox_64kb_mp3.zip
English.DickensCharles.Bleak House.zip
http://www.archive.org/download/bleak_house_cl_librivox/bleak_house_cl_librivox_64kb_mp3.zip

После этого использовать его относительно простоxargs:

curl "$u" -sL |
  jq -r '.books[] | "\(.language).\(.authors[0].last_name +.authors[0].first_name).\(.title).zip",.url_zip_file' |
  xargs -d '\n' -n2 wget -O

Где xargsиспользует две строки в качестве аргумента для wget, причем первая строка становится параметром опции -O, а вторая — URL-адресом.

Хотя я бы порекомендовал решение на основе Python -, подобное предложенному Джейми , за исключением использования JSON и встроенных в Python возможностей JSON вместо bs4.

1
27.01.2020, 23:32

Теги

Похожие вопросы