В GNU sed
:
sed -e '1i ;;' -e '$a ;;'
Он состоит из двух sed
выражений:
1i ;;
вставляет ( i
) ;;
(вставлена новая строка) перед первой строкой ( 1
)
$ a ;;
добавляет ( a
) ;;
(новая строка встроена) после последней строки ( $
)
Пример:
$ cat foo.txt
sdas
adas
$ sed -e '1i ;;' -e '$a ;;' foo.txt
;;
sdas
adas
;;
Поскольку у вас есть все файлы в add.txt
, предполагается, что имя файла не содержит никаких символов из IFS
(пробел, табуляция, новая строка по умолчанию) или подстановочных знаков ( *
, ?
, []
), вы можете сделать следующее, чтобы отредактировать файлы с расширением .bak
в качестве резервной копии оригинала:
sed -i.bak -e '1i ;;' -e '$a ;;' -- $(cat add.txt)
Без резервной копии:
sed -i -e '1i ;;' -e '$a ;;' $(cat add.txt)
Когда используется -i
, файлы берутся отдельно вместо одного поток, так что нам хорошо идти. Без -i
нам нужно использовать параметр -s
, чтобы получить отдельные потоки для файлов.
Или прочтите имена файлов, разделенные новой строкой, и выполните операции одно за другим с резервным копированием:
while IFS= read -r f; do sed -i.bak -e '1i ;;' -e '$a ;;' -- "$f"; done <add.txt
без резервного копирования:
while IFS= read -r f; do sed -i -e '1i ;;' -e '$a ;;' -- "$f"; done <add.txt
Задание для awk. Что-то вроде:
awk -F'|' -v fileformat="/abc/output/file_%04d.txt" -v max=3 -v field=5 '
NR == 1 {header = $0; next}
! ($field in seen) {
seen[$field]
if (++n % max == 1) {
close(out)
out = sprintf(fileformat, ++f)
print header > out
}
}
{print > out}' < /abc/input/a.txt
awkрешение:
awk -F'|' 'NR==1{ h=$0; f=0; c=1 }NR>1{
a[$5]; if(length(a)>3) { f=0;c++; delete a };
fn="file"c".txt"; if(!f) print h > fn; print > fn; f++
}' file
h=$0
-заголовок строка
f=0
-флаг, указывающий на момент печати строки заголовка в следующий новый файл
c=1
-Суффикс имени файла (увеличивается для каждого нового файла)
a[$5]
-индексирующий массив a
с уникальными значениями 5-го поля
if(length(a)>3) { f=0;c++; delete a }
-инициализация следующего нового имени файла(c++
)при следующих 3 уникальных значениях.(delete a
-удалить все элементы из массиваa
)
fn="file"c".txt"
-текущее имя файла
Просмотр результатов:
for f in file[0-9]*.txt; do echo "$f"; cat "$f"; echo; done
Выход:
file1.txt
C1|C2|C3|C4|C5|C6
0|1|2|3|0-1-2-3|4
0|2|2|4|0-1-2-3|5
0|1|2|3|1-3-2-4|4
0|1|2|3|1-1-3-4|4
0|1|2|3|1-1-3-4|5
file2.txt
C1|C2|C3|C4|C5|C6
0|1|2|3|4-5-2-6|4
0|1|2|3|4-5-2-6|6
0|4|5|3|7-4-2-4|4
0|1|2|3|7-4-2-5|4
0|1|2|3|7-4-2-5|5
0|1|2|3|7-4-2-5|6
file3.txt
C1|C2|C3|C4|C5|C6
0|1|2|3|7-5-2-6|5
#!/bin/bash
awk -F '|' '
function print_to_file(str) {
print str > "file_"file_num;
}
NR == 1 {header = $0;}
NR > 1 {
if(!buf) {
file_num = 1;
print_to_file(header);
}
if(buf != $5) {
buf = $5;
cnt++;
}
if(cnt > 3) {
cnt = 1;
file_num++;
print_to_file(header);
}
print_to_file($0);
}
' input.txt
Выход:
$ tail -n +1 -- file_* # display content of all files with their filenames
==> file_1 <==
C1|C2|C3|C4|C5|C6
0|1|2|3|0-1-2-3|4
0|2|2|4|0-1-2-3|5
0|1|2|3|1-3-2-4|4
0|1|2|3|1-1-3-4|4
0|1|2|3|1-1-3-4|5
==> file_2 <==
C1|C2|C3|C4|C5|C6
0|1|2|3|4-5-2-6|4
0|1|2|3|4-5-2-6|6
0|4|5|3|7-4-2-4|4
0|1|2|3|7-4-2-5|4
0|1|2|3|7-4-2-5|5
0|1|2|3|7-4-2-5|6
==> file_3 <==
C1|C2|C3|C4|C5|C6
0|1|2|3|7-5-2-6|5