Встроено Если с awk (фильтровать содержимое вывода)

Сawk:

NR == 1 {   # save the values from 1st line in array t
            split($0, t, FS);
        }

NR == 2 {   # compare values from second line with those stored in array t
            for ( i = 1; i <= NF; ++i ) {
                # build l1 and l2 (line 1 and line 2) based on comparison
                if ($i == 0 && t[i] == 0) {
                    l1 = (i == 1 ? 9    : l1 OFS 9    );
                    l2 = (i == 1 ? 9    : l2 OFS 9    );
                } else {
                    l1 = (i == 1 ? t[i] : l1 OFS t[i] );
                    l2 = (i == 1 ? $i   : l2 OFS $i   );
                }
            }
        }

END     {   # output the two constructed lines
            print l1;
            print l2;
        }

Запуск на примере файла:

$ awk -f script.awk file
1 9 9 9 9 9 9 9 9 9 1 2 1
0 9 9 9 9 9 9 9 9 9 0 0 0

Запуск для всех файлов, соответствующих wa_filtering_DP15_good_pops_snps_file_*в текущем каталоге:

mkdir modified

for name in wa_filtering_DP15_good_pops_snps_file_*; do
    awk -f script.awk "$name" >"modified/$name.new"
done

Это создаст новый файл для каждого входного файла с именем исходного файла и дополнительным суффиксом .new. Новые файлы будут помещены в папку modifiedв текущем каталоге.

  • Я решил создать новые файлы, чтобы оригиналы остались без изменений.
  • Я решил поместить новые файлы в новый каталог, так как наличие 22 миллионов файлов в одном каталоге может затруднить работу с файловой системой.

Старайтесь не создавать миллионы файлов в одном каталоге. Вместо этого либо

  1. создать множество подкаталогов и распределить файлы в них, возможно, на основе алгоритма биннинга, работающего с этим последним целым числом имени файла, или хэшем, или
  2. создать единый выходной файл, объединяющий все данные, возможно, с дополнительными строками текста, определяющими, к чему относятся следующие две строки.

Следующий вариант будет более эффективно работать на миллионах файлов:

FNR == 1    {   # save the values from 1st line in array t
                split($0, t, FS);
            }

FNR == 2    {   # compare values from second line with those stored in array t
                for ( i = 1; i <= NF; ++i ) {
                    # build l1 and l2 (line 1 and line 2) based on comparison
                    if ($i == 0 && t[i] == 0) {
                        l1 = (i == 1 ? 9    : l1 OFS 9    );
                        l2 = (i == 1 ? 9    : l2 OFS 9    );
                    } else {
                        l1 = (i == 1 ? t[i] : l1 OFS t[i] );
                        l2 = (i == 1 ? $i   : l2 OFS $i   );
                    }
                }

                # create output filename based on input filename
                # and output the two lines
                f = "modified/" FILENAME ".new";
                print l1 >f;
                print l2 >f;
            }

Чтобы запустить:

mkdir modified

find. -maxdepth 1 -type f -name 'wa_filtering_DP15_good_pops_snps_file_*' \
    -exec awk -f script.awk {} +

Новые файлы будут генерироваться в папке modified, как и раньше, но на этот раз будет запущена только часть процессов awk, а скорость обработки будет значительно увеличена.

0
10.01.2020, 20:34
1 ответ

Я тоже не уверен, что понимаю, но как далеко это вас заведет:

awk '/changeto/ {CTX = $NF} /# sh/ {FN = CTX "_" $NF} !/MASA1/ {print > FN}' file
0
28.01.2020, 02:57

Теги

Похожие вопросы