Como usar o sed com variáveis de caminho de arquivo E retornos de chamada regex E expressões aritméticas

2

Estou tendo um bom tempo obtendo a sintaxe adequada usando sed com variáveis contendo um caminho de arquivo, um retorno de chamada regex e uma expressão aritmática. Eu não sei como escapar das coisas corretamente.

Eu tenho um caminho de arquivo em um arquivo de texto com um número próximo a ele. Eu quero encontrar essa linha e incrementar o número.

FILE="/home/username/scripts/test.txt"
LINE="/home/username/Pictures/properties/wallpaper/span/tree.jpg"

sed -i -e "s,'$LINE' \([0-9]*\),'$LINE' $((+1))," $FILE

Por exemplo ..

/home/username/Pictures/properties/wallpaper/span/tree.jpg 2

deve se tornar ..

/home/username/Pictures/properties/wallpaper/span/tree.jpg 3

Qual é a melhor maneira de escapar do "." no caminho do arquivo? Como faço para implementar corretamente o retorno de chamada de e a expressão aritmética $((+1) ?

Atualmente estou recebendo um erro de +1 de token ruim.

    
por deanresin 28.04.2016 / 03:27

1 resposta

3

sed e aritmética não se misturam. A ferramenta certa para trabalhos como este é awk .

Considere este arquivo de teste:

$ cat test.txt
/nonmatching/line 1
/home/username/Pictures/properties/wallpaper/span/tree.jpg 2
/another/non/matching/line 5

Podemos incrementar o número da linha que você quer com:

$ line="/home/username/Pictures/properties/wallpaper/span/tree.jpg"
$ awk -v f="$line" '$0~f {$NF++} 1' test.txt
/nonmatching/line 1
/home/username/Pictures/properties/wallpaper/span/tree.jpg 3
/another/non/matching/line 5

Como você pode ver, isso incrementou o número na linha que correspondeu a $line .

Uma limitação é que esse código, conforme escrito, não preservará vários espaços em branco nas linhas para as quais o número é incrementado. Se os espaços em branco forem importantes, precisaríamos de mais definição do formato de entrada.

Como funciona

  • -v f="$line"

    Isso atribui o valor da variável do shell line à variável awk f .

  • $0~f {$NF++}

    Aqui, $0~f é uma condição. Isso é verdadeiro se a linha de entrada, denotada $0 , corresponder à regex f , conforme definido acima. Se corresponder, a instrução $NF++ será executada. Isso incrementa o último campo na linha que, para sua entrada, é o número.

  • 1

    Esta é uma abreviada enigmática do awk para imprimir a linha.

Editando um arquivo no local com awk

Se você tem um moderno GNU awk, você pode editar o arquivo com:

gawk -i inplace -v f="$line" '$0~f {$NF++} 1' test.txt

Com outros awks, use:

awk -v f="$line" '$0~f {$NF++} 1' test.txt > tmp.txt && mv -f tmp.txt test.txt

Criando text.txt se não existir

No caso de o arquivo test.txt não conter uma linha correspondente a $line , essa versão terá uma linha com 1 como a contagem:

gawk -i inplace -v f="$line" '$0~f {n=1; $NF++} 1; END{if(!n) print f,1>>FILENAME}' test.txt

Este código adiciona uma variável n . Se $line estiver no arquivo, n será definido como 1 . Se não for, n permanecerá no valor padrão de 0 . No END do arquivo de entrada, o valor de n é testado. Se n ainda for zero, a linha será adicionada.

    
por John1024 28.04.2016 / 03:53