Eu tenho um arquivo1 que se parece com isso
25 104.601 0.5
24.8488 104 0.5
24.5341 103 0.5
24.1844 102 0.5
24.1568 101 0.5
24.1568 100 0.5
24.1844 99 0.5
24.5341 98 0.5
Preciso encontrar o valor mínimo da coluna 1 e imprimi-lo em outro arquivo_NEW
Agora preciso repetir o procedimento acima para arquivos diferentes e encontrar o mínimo para pelo menos 100 arquivos.
Para que eu tenha uma saída final em file_NEW algo como isto
24.1568
23.3254 (from file2)
22.312 (from file3)
.....
Aqui, arquivo2 e arquivo3 têm conjuntos de dados semelhantes ao arquivo1. Todos os arquivos de entrada têm padrões de mesmo nome, como arquivo*.txt e estão no mesmo diretório
Alguém pode sugerir como fazer isso com awk ou sed?
Obrigado
Responder1
Para encontrar o valor mínimo, podemos usar o comando abaixo
Use o comando abaixo em cada arquivo
awk 'NR==1{sum=$1}($1 < sum){sum=$1}END{print sum}' filename >> outputfile
Testado e funcionou bem
Responder2
awk '{print $1 "\t(from " FILENAME ")"}' file* | sort -k1,1n | awk -F'\t' '!seen[$2]++'
O procedimento acima funcionará de forma robusta e eficiente em todos os seus arquivos de entrada de uma só vez, usando ferramentas padrão do UNIX, por exemplo:
$ cat file1
25 104.601 0.5
24.8488 104 0.5
24.5341 103 0.5
24.1844 102 0.5
24.1568 101 0.5
24.1568 100 0.5
24.1844 99 0.5
24.5341 98 0.5
$ cat file2
75 104.601 0.5
74.8488 104 0.5
74.5341 103 0.5
74.1844 102 0.5
74.1568 101 0.5
74.1568 100 0.5
74.1844 99 0.5
74.5341 98 0.5
$ awk '{print $1 "\t(from " FILENAME ")"}' file{1,2} | sort -k1,1n | awk -F'\t' '!seen[$2]++'
24.1568 (from file1)
74.1568 (from file2)
mas assume que nenhum dos nomes de arquivo contém caracteres de tabulação ou nova linha. Se eles contiverem guias, é um simples ajuste para lidar com eles:
awk '{print $1 "\t(from " FILENAME ")"}' file* |
sort -k1,1n |
awk '{f=$0; sub(/[^\t]*\t/,"",f)} !seen[f]++'
mas se eles também contiverem novas linhas, você precisará de ferramentas GNU para acomodar \0
terminadores (NUL):
awk -v ORS='\0' '{print $1 "\t(from " FILENAME ")"}' file* |
sort -z -k1,1n |
awk -v RS='\0' '{f=$0; sub(/[^\t]*\t/,"",f)} !seen[f]++'
Responder3
Uma sed
versão
find . -name "file*" -exec sh -c '
echo $(sort -nk1 "$1" | sed -n "1{s/ .*//p}" )" (from "${1##*/}")" ' sh {} \; | sort -nk1 > output.txt; cat output.txt
sort
inserindo o arquivo de saída, se necessário, e adicionando os nomes dos arquivos
Responder4
IIUC, você quer isso em cada arquivo:
awk 'NF' FILE | sort -n -k1 - | awk 'NR==1{print $1}' >> file_NEW
A inicial awk 'NF' FILE
é necessária caso você tenha linhas em branco vazias nos arquivos de entrada. Você não especificou se deseja executar este comando em todos os arquivos em um determinado diretório de forma recursiva ou não recursiva ou apenas em alguns arquivos com padrões específicos em seus nomes. De qualquer forma, você pode usar find
para fazer isso:
find . -name "FILE*" -exec sh -c 'awk "NF" FILE | sort -n -k1 - | awk "NR==1{print \$1}" >> file_NEW' sh {} \;
Neste caso, o comando acima é executado em todos os arquivos do diretório cujo nome começa com FILE
.
Observe também que isso não fornecerá necessariamente uma lista classificada na saída, file_NEW
porque find
executará tudo cegamente -exec
em cada arquivo que encontrar.