Разделить на несколько файлов на основе первого столбца при совпадении числовых значений диапазоны в другом столбце с awk

PF=(opt/N*.properties)
cp "${PF[@]}" /opt/backup

Пропустите цикл for и скопируйте все файлы в одной команде, таким образом глобус создает массив, а оболочка может расширять элементы в массиве в способ, показанный выше.

Если вы все еще хотите использовать цикл for, вы можете пропустить объявление переменной и просто выполнить для myfile в opt / N * .properties; делать ...

3
16.08.2017, 03:43
3 ответа

Однострочная команда awk:

awk -v P=-1 '$2<104 {if ($1>P+1)N=$1;P=$1;print $1,$2>"file"N".tmp"}'

Дает результат (, если вы не возражаете против имени файла)

==> file1.tmp <==
1   102.0184
2   100.2430
3   103.9029
4   102.7495
5   102.8825

==> file7.tmp <==
7 103.0479
8 101.2433

==> file10.tmp <==
10 101.5879
2
27.01.2020, 21:21
awk '{$0 = $2 < 104 ? NR : RS}1' inputfile |
sed -Ee '
   $aq
   /./,/^$/!d;/./H;$ba;/^$/ba;d;:a
   g;s/.//;s/\n.*\n|\n/,/;x;s/.*//;x
   s/(.*),(.*)/&w file_\1_\2.tmp/
   /,/!s/.*/&w file_&.tmp/
' | ed -s inputfile -

Здесь мы используем инструменты awk/sed/ed. Awkсначала генерирует номера строк для все те строки, которые меньше 104. Для других он печатает пустую строку. Затем приходит Sedи просматривает диапазоны строк от непустой строки до следующей пустой строки. И сохраняет номера строк в трюме. Теперь можно найти два типа диапазонов: n,m или обычный n. Используя их, мы создаем набор команд ed, который преобразует такие диапазоны в: n,mw file_n_m.tmp и file_n.tmp соответственно. Затем ed быстро обрабатывает входной файл, используя этот динамически сгенерированный ed-скрипт, чтобы поместить строки в свои файлы .tmp.

Вот один из способов выполнить вашу задачу с помощью Perl:

perl -lane '
   BEGIN { $fmt = sprintf q[%s%%s\n%s], (chr 39)x2; }
   if ( $F[1] < 104 ) {
      push @A, "@F[0,1]";
      if ( eof ) {
         my $f = join $", q<printf>, $fmt, map(qq[\"$_\"], @A), q[>], (( ! defined $a ) ? qq[file_${.}.tmp] : qq[file_${a}_${.}.tmp]);
         system("$f");
      } else { $a //= $.; }
   } else {
      next if ! defined $a;
      $b //= $.-1;
      my $f = join $", q<printf>, $fmt, map(qq[\"$_\"], @A), q[>], (( $a == $b ) ? qq[file_$b.tmp] : qq[file_${a}_$b.tmp]);
      system("$f");
      ($a, $b, @A) = (undef)x2;
   }
' yourfile

Результаты:

Учитывая ввод, создаются следующие 3 файла: file_1_5.tmp file_7_8.tmp file_10.tmp с содержимым

% больше file_1_5.tmp file_7_8.tmp file_10.tmp

::::::::::::::
file_1_5.tmp
::::::::::::::
1 102.0184
2 100.2430
3 103.9029
4 102.7495
5 102.8825
::::::::::::::
file_7_8.tmp
::::::::::::::
7 103.0479
8 101.2433
::::::::::::::
file_10.tmp
::::::::::::::
10 101.5879

Объяснение:

Сначала основная идея верхнего уровня: мы следим за тем, не отстает ли второе поле от числового 104.В сценарии, когда это происходит, означает, что нам нужно напечатать предыдущий диапазон. Просто имейте в виду, что для диапазонов unilength имя файла изменяется соответствующим образом, чтобы отразить это.

Другой случай, когда мы находимся в процессе накопления текущего диапазона ($F[1] < 104), просто имейте в виду, что при этом, если мы нажмем eof, нам нужно распечатать диапазон сейчас.

P.S.: Команда systemсоздается динамически с использованием динамически создаваемого формата, ее данные представляют собой первое и второе поля, и, наконец, имя файла .tmp создается в соответствии с диапазоном.

$aи $b— номера начала/конца строки диапазона. Их состояния будут информировать нас для принятия надлежащих решений.

0
27.01.2020, 21:21

Ниже представлена ​​awkпрограмма. Вы можете поиграть со столбцом и порогом, указанным в аргументах :

.
awk -v column=2 -v threshold=104 '
    function save() { if (lines != "") print lines >"file_" first "-" last ".txt" }

    ! ($column < threshold) {
        save()
        first = last = lines = ""
        next
    }

    { 
        if (first == "") first = $1
        last = $1
        lines = lines $1 OFS $column ORS
    }

    END { save() }
'

Обратите внимание, что непрерывные строки сохраняются в памяти до тех пор, пока они не будут сохранены. Если у вас есть сотни миллионов непрерывных строк, это решение следует адаптировать (, сохраняя каждую строку во временном файле, а затем переименовывая его, когда встречается последняя строка непрерывного блока ).

1
27.01.2020, 21:21

Теги

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