Командный состав в баше


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

http://somewhere.com/foo1.xml.gz
http://somewhere.com/foo2.xml.gz
...
Мне нужно запустить XML в каждом файле через xmlstarlet, поэтому я делаю ... | xargs gzip -d | xmlstarlet ..., за исключением того, что я хочу, чтобы xmlstarlet вызывался один раз для каждой строки, входящей в gzip, а не для всех xml-документов, добавленных друг к другу. Возможно ли compose 'gzip -d' 'xmlstarlet ...', чтобы xargs предоставлял один аргумент каждой из своих составных функций?
4 2

4 ответа:

Почему бы не прочитать ваш файл и не обработать каждую строку отдельно в оболочке? то есть

fileList=/path/to/my/xmlFileList.txt
cat ${fileList} \
| while read fName ; do
   gzip -d ${fName} | xmlstartlet > ${fName}.new
done 

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

Используйте GNU Parallel:

cat filelist | parallel 'zcat {} | xmlstarlet >{.}.out'

Или если вы хотите включить выборку URL-адресов:

cat urls | parallel 'wget -O - {} | zcat | xmlstarlet >{.}.out'

Его легко читать,и вы получаете дополнительное преимущество от параллельного выполнения заданий на ЦП. Смотрите вступительное видео, чтобы узнать больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Хотя правильный ответ-это тот, который предлагает shelter (+1), вот однострочный "дивертисмент " при условии, что вход-это предложенный Андреем (a command, который генерирует список URL): -)

~$ eval $(command | awk '{a=a "wget -O - "$0" | gzip -d | xmlstartlet > $(basename "$0" .gz ).new; " } END {print a}')

Он просто генерирует мультикомандную строку, которая делает wget http://foo.xml.gz | gzip -d | xmlstartlet > $(basenname foo.xml.gz .gz).new для каждого из URL-адресов во входных данных; после того, как результирующая команда оценена

Если xmlstarlet может работать на stdin вместо того, чтобы передавать ему имя файла, то:

some command | xargs -i -n1 sh -c 'zcat "{}" | xmlstarlet options ...'

Опция xargs -i означает, что вы можете использовать заполнитель "{}", чтобы указать, куда должно идти имя файла. Используйте -n 1, чтобы указать, что xargs следует только по одной строке за раз от его входа.