Eu me deparei com uma pergunta (no próprio SO) em que o OP precisa editar e salvar a operação no próprio Input_file (s).
Sei por um único arquivo Input_file que poderíamos fazer o seguinte:
awk '{print "test here..new line for saving.."}' Input_file > temp && mv temp Input_file
Agora, digamos que precisamos fazer alterações no mesmo tipo de formato de arquivo (assuma .txt aqui).
O que tentei / pensei para este problema: Sua abordagem é passar por um loop for de arquivos .txt e chamar singleawk
é um processo doloroso e NÃO recomendado, pois desperdiçará ciclos desnecessários da CPU e, para um número maior de arquivos, seria mais lento.
Então, o que possivelmente poderia ser feito aqui para executar edição no local de vários arquivos com um NON GNU awk
que não suporta a opção inplace. Também passei por esse segmento. Salvar modificações no local com o awk, mas não há muito para o vice NÃO do GNU awk e alterar vários arquivos no local awk
, pois um awk não GNU não terá inplace
opção.
OBSERVAÇÃO: Por que estou adicionandobash
tags, desde que, na parte de resposta, usei os comandos bash para renomear arquivos temporários para seus nomes reais de Input_file, adicionando-os.
EDIT: De acordo com o comentário de Ed sir, adicionando um exemplo de amostras aqui, embora a finalidade do código deste segmento também possa ser usada por edição genérica no local.
Arquivos de entrada de amostra:
cat test1.txt
onetwo three
tets testtest
cat test2.txt
onetwo three
tets testtest
cat test3.txt
onetwo three
tets testtest
Amostra da saída esperada:
cat test1.txt
1
2
cat test2.txt
1
2
cat test3.txt
1
2
awk
(talvez em um subshell) ou um{...}
grupo fechado e depois gravar os resultados no arquivo de saída desejado (para cada arquivo de entrada, ou um arquivo combinado para todos os arquivos de entrada). Então você simplesmente redireciona a saída do subshell ou grupo de chaves para o arquivo atual que está sendo gravado? Simplesmente incluir uma sequência de arquivos de entrada após oawk
comando processaria sequencialmente todos os arquivos (ou algo semelhante)?awk {..} file1 .. fileX
escrever o arquivo modificado, como, por exemplo,temp01
e em sua próxima iteração ao processar o próximo arquivo, use amv -f tmp01 input01
para sobrescrever o arquivo de entrada com os dados modificados; ou (2) basta escrever um novo diretório./tmp/tmp01 ... ./tmp/tmp0X
durante a execução doawk
script e acompanhar com um loop sobre os arquivos no./tmp
diretório e, por exemplomv -f "$i" "input_${i##*[^0-9]}"
(ou qualquer expansão necessária para substituir os arquivos de entrada antigos)awk
a conclusão completa do código, a segunda opção é quase a mesma que eu estou usando na minha sugestão. fique agradecido se você puder informar seus pensamentos sobre essa solução, senhor.Respostas:
Como o objetivo principal deste segmento é como fazer o SAVE local no GNU,
awk
por isso estou publicando primeiro seu modelo que ajudará qualquer pessoa em qualquer tipo de requisito, eles precisam adicionar / acrescentarBEGIN
eEND
seção em seu código, mantendo seu BLOCO principal conforme seus requisito e deve fazer a edição local:OBSERVAÇÃO: O seguinte gravará toda a saída em output_file; caso deseje imprimir alguma coisa na saída padrão, adicione apenas a
print...
declaração sem as> (out)
seguintes.Modelo genérico:
Solução específica da amostra fornecida:
Eu vim com a seguinte abordagem em
awk
si (para exemplos adicionados a seguir é minha abordagem para resolver isso e salvar a saída no arquivo Input_file)NOTA: este é apenas um teste para salvar a saída editada nos arquivos de entrada, pode-se usar a seção BEGIN, juntamente com a seção END do programa, a seção principal deve ser conforme o requisito da pergunta específica.
Aviso justo: também como essa abordagem cria um novo arquivo temporário de saída no caminho, é melhor garantir que tenhamos espaço suficiente nos sistemas, embora no resultado final isso mantenha apenas os principais arquivos_de_ entrada, mas durante as operações ele precisará de espaço no sistema / diretório
A seguir, é apresentado um teste para o código acima.
Execução do programa com um exemplo: Vamos supor que sejam os
.txt
arquivos_de_ entrada:Agora, quando executamos o seguinte código:
NOTA: Eu coloquei
ls -lhtr
nasystem
seção intencionalmente para ver quais arquivos de saída ele está criando (base temporária), porque mais tarde os renomeará para o nome real.Quando fazemos um script
ls -lhtr
apósawk
a execução, poderíamos ver apenas.txt
arquivos lá.Explicação: Incluindo uma explicação detalhada do comando acima aqui:
fonte
FNR==1
bloco, ainda poderá salvar as alterações no local. Likeawk 'FNR==1{system("rm " FILENAME)} {print "new lines" > FILENAME}' files...
. Isso não é confiável (é provável que a perda completa de dados ocorra), mas ainda assim funciona principalmente: DEu provavelmente usaria algo assim se tentasse fazer isso:
Eu preferiria copiar o arquivo original para o backup primeiro e depois operar para salvar as alterações no original, mas isso mudaria o valor da variável FILENAME para cada arquivo de entrada indesejável.
Observe que, se você tiver um arquivo original com o nome
whatever.bak
ouwhatever.new
em seu diretório, substitua-o por um arquivo temporário, para que você também precise adicionar um teste. Uma chamada paramktemp
obter os nomes dos arquivos temporários seria mais robusta.A coisa MUITO mais útil a ter nessa situação seria uma ferramenta que executa qualquer outro comando e faz a parte de edição "local", pois isso poderia ser usado para fornecer edição "local" para POSIX sed, awk, grep, tr, o que for e não exigiria que você altere a sintaxe do seu script para
print > out
etc. sempre que desejar imprimir um valor. Um exemplo simples e frágil:que você usaria da seguinte maneira:
Um problema óbvio com esse
inedit
script é a dificuldade de identificar os arquivos de entrada / saída separadamente do comando quando você possui vários arquivos de entrada. O script acima supõe que todos os arquivos de entrada apareçam como uma lista no final do comando e o comando é executado contra eles um de cada vez, mas é claro que isso significa que você não pode usá-lo para scripts que requerem 2 ou mais arquivos em um tempo, por exemplo:ou scripts que definem variáveis entre arquivos na lista arg, por exemplo:
Tornando-o mais robusto deixado como um exercício para o leitor, mas olhe para a
xargs
sinopse como um ponto de partida para como um robustoinedit
precisaria funcionar :-).fonte
A solução shell é simples e provavelmente rápida o suficiente:
Procure uma solução diferente apenas se tiver demonstrado conclusivamente que isso é muito lento. Lembre-se: a otimização prematura é a raiz de todo mal.
fonte