Encontre o valor mínimo em uma coluna de vários arquivos e imprima em outro arquivo

Encontre o valor mínimo em uma coluna de vários arquivos e imprima em outro arquivo

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 \0terminadores (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 sedversã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

sortinserindo 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 findpara 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_NEWporque findexecutará tudo cegamente -exec em cada arquivo que encontrar.

informação relacionada