Объединить семь файлов с помощью awk построчно

Объединить семь файлов с помощью awk построчно

У меня есть семь (или восемь и т. д.) файлов с одинаковым количеством строк.

файл1

1.001
1.002
1.003
1.004

файл2

2.001
2.002
2.003
2.004

файл3

3.001
3.002
3.003
3.004

и т. д.

Желаемый результат:

1.001;2.001;3.001;4.001;5.001;6.001;7.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004

Как это сделать с помощью короткого скрипта в awk?

решение1

Как сказал steeldriver, разумный способ сделать это — это paste:

$ paste -d';' file*
1.001;2.001;3.001;4.001;5.001;6.001;7.001;8.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002;8.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003;8.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004;8.004

Но если вам необходимо использовать awk:

$ awk '{a[FNR]=a[FNR](FNR==NR?"":";")$0} END{for (i=1;i<=FNR;i++) print a[i]}' file*
1.001;2.001;3.001;4.001;5.001;6.001;7.001;8.001
1.002;2.002;3.002;4.002;5.002;6.002;7.002;8.002
1.003;2.003;3.003;4.003;5.003;6.003;7.003;8.003
1.004;2.004;3.004;4.004;5.004;6.004;7.004;8.004

Скрипт awk хранит все данные в памяти. Если файлы большие, это может быть проблемой. Но для этой задачи pasteлучше и проще в любом случае.

Как это работает

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

  • a[FNR]=a[FNR](FNR==NR?"":";")$0

    FNR— номер строки текущего файла, который мы читаем, и $0содержимое этой строки. Этот код добавляется $0к концу a[FNR]. За исключением случая, когда мы все еще читаем первый файл, мы ставим точку с запятой перед $0. Это делается с помощью сложного на вид тернарного оператора: (FNR==NR?"":";"). На самом деле это просто команда if-then-else. Если мы читаем первый файл, то есть if FNR==NR, то она возвращает пустую строку "". В противном случае она возвращает точку с запятой, ;.

  • END{for (i=1;i<=FNR;i++) print a[i]}

    После того, как мы закончим чтение всех файлов, эта команда выведет на экран данные, которые мы накопили в массиве a.

решение2

POSIX Awk; это работает с произвольным количеством файлов, и файлы даже не обязательно должны иметь одинаковое количество строк. Скрипт продолжает работать, пока все файлы не закончатся строками:

BEGIN {
  do {
    br = ch = 0
    while (++ch < ARGC)
      if (getline < ARGV[ch]) {
        printf ch < ARGC - 1 ? $0 ";" : $0 RS
        br = 1
      }
  } while (br)
}

Связанный контент