У меня есть семь (или восемь и т. д.) файлов с одинаковым количеством строк.
файл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. Если мы читаем первый файл, то есть ifFNR==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)
}