У меня есть файл1, который выглядит так
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
Мне нужно найти минимальное значение из столбца 1 и вывести его в другом файле_NEW
Теперь мне нужно повторить вышеизложенное для разных файлов и найти минимум для 100 файлов.
Так что у меня будет конечный вывод в file_NEW что-то вроде этого
24.1568
23.3254 (from file2)
22.312 (from file3)
.....
Здесь file2 и file3 имеют похожие наборы данных, как file1. Все входные файлы имеют одинаковые шаблоны имен, например file*.txt, и находятся в одном каталоге.
Может ли кто-нибудь подсказать, как это сделать с помощью awk или sed?
Спасибо
решение1
Чтобы найти минимальное значение, мы можем использовать следующую команду:
Используйте следующую команду для каждого файла
awk 'NR==1{sum=$1}($1 < sum){sum=$1}END{print sum}' filename >> outputfile
Проверено и работает отлично
решение2
awk '{print $1 "\t(from " FILENAME ")"}' file* | sort -k1,1n | awk -F'\t' '!seen[$2]++'
Вышеуказанное будет работать надежно и эффективно со всеми вашими входными файлами одновременно с использованием стандартных инструментов UNIX, например:
$ 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)
но предполагает, что ни одно из имен ваших файлов не содержит символов табуляции или новой строки. Если они содержат табуляции, то это простая настройка для их обработки:
awk '{print $1 "\t(from " FILENAME ")"}' file* |
sort -k1,1n |
awk '{f=$0; sub(/[^\t]*\t/,"",f)} !seen[f]++'
но если они также содержат символы новой строки, то вам понадобятся инструменты GNU для поддержки \0
(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]++'
решение3
Версияsed
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
при необходимости скопируйте выходной файл и добавьте имена файлов
решение4
IIUC, вам нужно это для каждого файла:
awk 'NF' FILE | sort -n -k1 - | awk 'NR==1{print $1}' >> file_NEW
Начальная awk 'NF' FILE
нужна в случае, если у вас были пустые строки во входных файлах. Вы не указали, хотите ли вы запустить эту команду для всех файлов в указанном каталоге рекурсивно или нерекурсивно или только для некоторых файлов с определенными шаблонами в именах. В любом случае, вы можете использовать find
для этого:
find . -name "FILE*" -exec sh -c 'awk "NF" FILE | sort -n -k1 - | awk "NR==1{print \$1}" >> file_NEW' sh {} \;
В этом случае указанная выше команда выполняется для всех файлов в указанном каталоге, имя которых начинается с FILE
.
Также обратите внимание, что это не обязательно даст вам отсортированный список на выходе, file_NEW
поскольку find
будет слепо выполняться все последующее -exec
для каждого найденного файла.