Alguém pode sugerir uma maneira elegante de fazer isso?
Entrada:
test instant ()
test instant ()
...
test instant () //total 1000 lines
a saída deve ser:
test instant1 ()
test instant2 ()
test instant1000()
As linhas vazias estão nos meus arquivos de entrada e há muitos arquivos no mesmo diretório que eu preciso processar de uma só vez.
Eu tentei isso para substituir muitos arquivos no mesmo diretório e não funcionou.
for file in ./*; do perl -i -000pe 's/instance$& . ++$n/ge' "$file"; done
erros:
Substitution replacement not terminated at -e line 1.
Substitution replacement not terminated at -e line 1.
e eu também tentei isso: perl -i -pe 's/instant/$& . ++$n/ge' *.vs
Funcionou, mas o índice continuou aumentando de um arquivo para outro. Eu gostaria de redefinir isso para 1 para o arquivo diff. alguma sugestão boa?
find . -type f -exec perl -pi -e 's/instant/$& . ++$n{$ARGV}/ge' {} +
funciona, mas substituiu todos os outros arquivos não devem ser substituídos. Prefiro substituir apenas os arquivos por "* .txt".
test instant ()
?Respostas:
ou com GNU
awk
:Para editar os arquivos no local, adicione a
-i
opção aperl
:Ou recursivamente:
Explicações
-p
é processar a entrada linha por linha, avaliar a expressão passada-e
para cada linha e imprimi-la. Para cada linha, substituímos (usando os/re/repl/flags
operador)instant
por si ($&
) e o valor incrementado de uma variável++$n
. Ag
bandeira é fazer a substituição em todo o mundo (e não apenas uma vez), ee
para que a substituição seja interpretada como código Perl para e valuate (não uma seqüência fixa).Para edição no local em que uma chamada perl processa mais de um arquivo, queremos
$n
redefinir a cada arquivo. Em vez disso, usamos$n{$ARGV}
(onde$ARGV
está o arquivo processado no momento).O
awk
que merece um pouco de explicação.Estamos usando a capacidade do GNU
awk
para separar registros em cadeias arbitrárias (mesmo regexps). Com-vRS=instant
, definimos o separador de registros comoinstant
.RT
é a variável que contém o que foi correspondidoRS
, normalmente,instant
exceto o último registro onde será a sequência vazia. Na entrada acima, os registros ($0
) e terminadores de registro (RT
) são ([$0|RT]
):Então, tudo o que precisamos fazer é inserir um número incremental no início de cada registro, exceto o primeiro.
Qual é o que fazemos acima. Para o primeiro registro,
n
estará vazio. Definimos ORS (o separador de registros de saída ) como RT, para que sejaawk
impresson $0 RT
. Faz isso na segunda expressão (++n
), que é sempre uma condição avaliada como verdadeira (um número diferente de zero) e, portanto, a ação padrão (de impressão$0 ORS
) é executada para cada registro.fonte
sed
realmente não é a melhor ferramenta para o trabalho, você deseja algo com melhores recursos de script. Aqui estão algumas opções:perl
O
-p
meio "imprime todas as linhas" após aplicar o script fornecido-e
. As-000
voltas no "modo de parágrafo" para registros (linhas) são definidos pela nova linha consecutiva (\n
) caracteres, isso permite que lidar com linhas espaçadas duplas corretamente.$&
é o último padrão correspondente e$.
é o número da linha atual do arquivo de entrada. Oe
ins///e
me permite avaliar expressões no operador de substituição.awk (isso pressupõe que seus dados são exatamente como mostrados, com três campos separados por espaço)
Aqui, incrementamos a
k
variávelk
apenas se a linha atual não estiver vazia;/./
nesse caso, também imprimimos as informações necessárias. Linhas vazias são impressas como estão.várias conchas
Aqui, cada linha de entrada é dividida automaticamente no espaço em branco e os campos são salvos como
$a
,$b
e$c
. Em seguida, dentro do loop,$c
é aumentado em um para cada linha que$a
não está vazia e seu valor atual é impresso ao lado do segundo campo$b
.NOTA: todas as soluções acima assumem que todas as linhas no arquivo têm o mesmo formato. Caso contrário, a resposta de @ Stephane é o caminho a percorrer.
Para lidar com muitos arquivos e supondo que você queira fazer isso com todos os arquivos no diretório atual, você pode usar o seguinte:
CUIDADO: Isso pressupõe nomes de arquivos simples, sem espaços, se a necessidade de lidar com algo mais complexo, ir para (assumindo
ksh93
,zsh
oubash
):fonte