como somar a saída de awk ou outra expressão com xargs

3

Suponha que eu tenha o seguinte script de shell bash:

#!/bin/bash
export  count=0;
for i in 'ls ./mydoc' ;do

     pdfinfo ./mydoc/$i | egrep Pages |awk {'print $2'} |xargs -+ $count   ;
                                                        ^^^^^^^^^^^^^^^^^
done;

echo $count;

Enumera páginas de cada arquivo pdf, mas não sei como juntá-las. !!!!!

    
por PersianGulf 29.08.2012 / 23:27

3 respostas

9

Apenas faça no awk, esqueça xargs.

awk '{total += $2} END {print total}'

mas você precisa executar o awk apenas uma vez, com toda a saída do loop conectada a ele. E por que não eliminar o grep separado também ...

for i in mydoc/* ; do
    pdfinfo $i
done | awk '/^Pages/ { total += $2 } END { print total }'
    
por 29.08.2012 / 23:33
3

Experimente o método de cálculo integrado:

#!/bin/bash
count=0
for i in ./mydoc/* ; do
  count=$(( $count + $(pdfinfo "$i" | grep Pages |awk {'print $2'}) ))
done
echo $count
    
por 29.08.2012 / 23:38
2

A resposta awk aceita por Alan é boa, mas aqui está uma solução genérica usando xargs e bc . A idéia é gerar uma lista de números de alguma forma, usar xargs para uni-los em uma linha separada por espaços e usar sed para alterar os espaços para + caracteres ( tr também funcionaria ). canaliza isso para bc.

O mesmo método pode ser usado para construir um regexp a partir de uma lista de strings / regexps, apenas altere os espaços para | (regexp estendido) ou \| (regexp básico) em vez de + :

for i in mydoc/* ; do pdfinfo $i ; done | \
  awk '/^Pages/ {print $2}' | xargs | sed -e 's/ /+/g' | bc

NOTA: se houver muitos milhares de números gerados, excedendo o limite de comprimento da linha de comando do shell, os xargs podem gerar várias linhas. Como a saída de bc se qualifica como " gera uma lista de números de alguma forma ", a solução é canalizar a saída de bc para xargs | sed -e 's/ /+/g' | bc novamente.

for i in mydoc/* ; do pdfinfo $i ; done | \
  awk '/^Pages/ {print $2}' | xargs | sed -e 's/ /+/g' | bc | \
  xargs | sed -e 's/ /+/g' | bc

xargs | sed -e 's/ /+/g' | bc | xargs | sed -e 's/ /+/g' | bc pode, é claro, ser colocado em um script de shell, função ou alias.

e aqui está um exemplo de como construir um regexp usando esse método. Se search.txt contiver foo, bar, baz, quux (uma palavra por linha), então:

$ cat search.txt | xargs | sed -e 's/ /|/g'
foo|bar|baz|quux

o uso inútil de gato é um marcador de lugar para este exemplo - substitua qualquer canal que gere uma lista de palavras ou padrões regulares.

Se qualquer um dos padrões de pesquisa contiver caracteres de espaço, você terá que alterá-los para outra coisa (escolha algo que provavelmente não está na entrada) temporariamente, antes de enviar para xargs e depois alterá-los novamente após o %código%. por exemplo. se a linha 'bar' do search.txt tiver um espaço à direita:

$ cat search.txt | sed -e 's/ /XXX_SPACE_CHARACTER_XXX/g' | xargs | sed -e 's/ /|/g' -e 's/XXX_SPACE_CHARACTER_XXX/ /g'
foo|bar |baz|quux
    
por 30.08.2012 / 03:34