распределять данные как в порядке увеличения, так и в порядке уменьшения - PullRequest
0 голосов
/ 16 июня 2020

У меня есть файл с количеством строк n, я хочу, чтобы его данные распределялись по 7 файлам в соответствии с порядком, указанным ниже .

Входной файл

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
5
16
17
.
.
28

Выходной файл

 1  2  3  4  5 6  7
14 13 12 11 10 9  8 
15 16 17 18 19 20 21
28 27 26 25 24 23 22

поэтому, если я открою первый файл, он должен иметь строки

1
14
15
28

аналогично если я открою второй файл, он должен иметь строки

2
13
16
27

, аналогичный вывод и для других файлов.

Кто-нибудь может помочь, с приведенным ниже кодом он делает то, что требуется, но не в необходимом порядке.

awk '{print > ("te1234"++c".txt");c=(NR%n)?c:0}' n=7 test6.txt
1  2  3  4  5  6  7
8  9  10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28

Ответы [ 4 ]

2 голосов
/ 16 июня 2020

Счетчик выходного файла может уменьшаться для каждой второй группы из семи человек:

awk 'FNR%n==1 {asc=!asc}
    {
        out="te1234" (asc ? ++c : c--) ".txt";
        print >> out;
        close(out)
    }' n=7 test6.txt
2 голосов
/ 16 июня 2020

РЕДАКТИРОВАТЬ: Поскольку OP изменил образец Input_file совершенно другим, поэтому добавляя это решение сейчас, снова оно написано и протестировано только с показанными образцами.

С xargs + одиночный awk: (рекомендуемый)

xargs -n7 < Input_file | 
awk '
FNR%2!=0{
  for(i=1;i<=NF;i++){
    print $i >> (i".txt")
    close(i".txt")
  }
  next
}
FNR%2==0{
   for(i=NF;i>0;i--){
     count++
     print $i >> (count".txt")
     close(i".txt")
   }
   count=""
}'

Исходное решение:

xargs -n7 < Input_file | 
awk '
FNR%2==0{
  for(i=NF;i>0;i--){
    val=(val?val OFS:"")$i
  }
  $i=val
  val=""
}
1' | 
awk '
{
  for(i=1;i<=NF;i++){
    print $i >> (i".txt")
    close(i".txt")
  }
}'

Вышеупомянутое может быть выполнено с помощью одного awk тоже добавит xargs + awk (одно) решение за несколько минут.



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

awk '{for(i=1;i<=NF;i++){print $i >> (i".txt");close(i".txt")}}' Input_file
1 голос
/ 16 июня 2020
$ ls
file    tst.awk

$ cat tst.awk
{ rec = (cnt % 2 ? $1 sep rec : rec sep $1); sep=FS }
!(NR%n) {
    ++cnt
    nf = split(rec,flds)
    for (i=1; i<=nf; i++) {
        out = "te1234" i ".txt"
        print flds[i] >> out
        close(out)
    }
    rec=sep=""
}

.

$ awk -v n=7 -f tst.awk file

.

$ ls
file        te12342.txt te12344.txt te12346.txt tst.awk
te12341.txt te12343.txt te12345.txt te12347.txt

$ cat te12341.txt
1
14
15
28

$ cat te12342.txt
2
13
16
27

Если вы можете ввести ввод, который не является точным кратным n, переместите код, который в настоящее время находится в !(NR%n) заблокировать функцию и вызвать эту функцию там и в разделе END.

0 голосов
/ 16 июня 2020

Это может сработать для вас (GNU sed и parallel):

parallel  'echo {1}~14w file{1}; echo {2}~14w file{1}' ::: {1..7} :::+ {14..8} |
sed -n -f - file && 
paste file{1..7}

Создайте сценарий sed для записи файлов с именем filen, где n от 1 до 7 (см. Выше первый набор параметров в параллельной команде а также в команде paste).

Сценарий sed использует адрес n~m, где n - это начальный адрес, а m - по модулю после него.

Распространенные файлы сначала создается, а затем команда вставки объединяет их все вместе, чтобы создать один выходной файл (по умолчанию разделены табуляцией, используйте параметр вставки -d, чтобы получить желаемый разделитель).

Альтернатива с использованием Bash & sed:

for ((n=1,m=14;n<=7;n++,m--));do echo "$n~14w file$n";echo "$m~14w file$n";done |
sed -nf - file && 
paste file{1..7}
...