Diminuindo um número com sed

3

Eu extraí os metadados de um PDF em um arquivo .txt usando pdftk e agora estou tentando diminuir o valor de BookmarkPageNumber de cada indicador por um número inteiro. O .txt tem estas linhas:

BookmarkBegin
BookmarkTitle: Preface
BookmarkLevel: 1
BookmarkPageNumber: 10
BookmarkBegin
BookmarkTitle: Author
... and so on

Estou tentando fazer isso usando o comando substituto do sed e aqui está o que eu tenho até agora:

// $1 is the source .txt file; $2 is the decrement
// __ is a placeholder for the variable with the original value
cat $1 | sed "s/BookmarkPageNumber: [0-9]*/BookmarkPageNumber: 'expr __ - $2'/" | cat > metadata.txt

Como posso colocar o valor original em uma variável e, em seguida, substituir o palceholder __ por ele, nessa mesma expressão sed?

    
por netcentric 26.10.2014 / 15:14

4 respostas

9

Para isso, é melhor usar awk para suportar operações aritméticas

cat $1 | awk -v d=$2 '/BookmarkPageNumber:/{$2-=d}1'
    
por 26.10.2014 / 15:31
5
awk '!/BookmarkPageNumber:/ {print}; /BookmarkPageNumber:/ {print $1 " " $2-1}' old.txt > new.txt
    
por 26.10.2014 / 16:29
4

Outra opção seria usar o próprio shell (usando 5 como exemplo, altere-o para qualquer que seja o inteiro real que você deseja subtrair):

while read key val; do 
    [[ $key == "BookmarkPageNumber:" ]] && let val=val-5;
    echo $key $val; 
done < file 

Você também pode usar uma ferramenta como perl :

perl -pe 's/(BookmarkPageNumber:\s*)(\d+)$/$1 . ($2-5)/e; ' file 

E aqui está outra abordagem de awk :

awk '$1~/BookmarkPageNumber:/{$2=$2-5}1;' file 
    
por 26.10.2014 / 18:53
3

NOTA: Eu acabei de perceber que ele queria diminuir o BookmarkPageNumber por um inteiro arbitrário, que eu inicialmente inspecionei, e a minha solução abaixo só funciona para diminuí-lo em 1. No entanto, eu me sinto pressionado a remover inteiramente considerando o esforço que eu coloquei para ele:

-------- apenas solução parcial ---------

Caso você esteja determinado a usar apenas o sed, eu tenho este 1 liner para você: sed -r '/^BookmarkPageNumber: /{s/([0-9]*)$/@/;:loop {s/0@/@9/;/0@/b loop;};s/1@/_0/;s/2@/_1/;s/3@/_2/;s/4@/_3/;s/5@/_4/;s/6@/_5/;s/7@/_6/;s/8@/_7/;s/9@/_8/;s/ @9+$/ UNDERFLOW/;s/ _0*/ /;s/_//}' $1 >metadata.txt

Nota: isso só funciona para números decimais naturais, espero que esteja tudo bem para você.

Ah, ainda tem detecção de underflow. Então, caso você queira que seus números de página sejam saturados em 0, basta substituir UNDERFLOW por 0

E eu concordo com qualquer um que chama isso de mera manobra intelectual, porque é isso que é.

p.s .: você provavelmente deve verificar se os descritores de arquivos de entrada e saída não apontam para o mesmo arquivo, senão o arquivo será truncado se o usuário tiver acesso de gravação.

    
por 27.10.2014 / 17:49