Как я могу внести изменения только в первую строку файла?
Я хотел бы знать, какой шаблон я могу использовать в sed для внесения изменений в первую строку огромных файлов (~2 ГБ). Предпочтение sed только потому, что я предполагаю, что он должен быть быстрее, чем скрипт на Python или Perl.
Файлы имеют следующую структуру:
field 1, field 2, ... field n
data
И, учитывая вероятность наличия пробелов в идентификаторе для каждого поля, мне нужно заменить каждый пробел подчеркиванием следующим образом:
**BEFORE**
the first name,the second name,the first surname,a nickname, ...
data
**AFTER**
the_first_name,the_second_name,the_first_surname,a_nickname, ...
data
Любые указатели на правильный шаблон для использования, или другой скриптовое решение было бы отличным.
5 ответов:
Для редактирования первых 10 строк
sed -i -e '1,10s/ /_/g'
В Perl можно использовать оператор триггера в скалярном контексте:
perl -i -pe 's/ /_/g if 1 .. 10'
Я не думаю, что вы хотите использовать какое-либо решение, которое требует записи данных в новый файл.
Если вы уверены, что все, что вам нужно, - это изменить пробелы на подчеркивания в первой строке больших текстовых файлов, вам нужно только прочитать первую строку, поменять местами символы и записать ее обратно:
#!/usr/bin/env perl use strict; my $filename = shift; open (FH, "+< $filename") || die "can't open $filename: $!"; my $line = <FH>; $line =~ s/ /_/g; seek FH, 0, 0; # go back to the start of the file printf FH $line; close FH;
Чтобы использовать его, просто передайте полный путь файла для обновления:
# fixheader "/path/to/myfile.txt"
Вы вряд ли заметите разницу в скорости между Perl, Python, и сед. Ваш сценарий будет тратить большую часть своего времени на ожидание ввода-вывода.
Если строки одинаковой длины, вы можете редактировать на месте, в противном случае вы придется создать новый файл.
В Perl:
#!/usr/bin/env perl use strict; my $filename = shift; open my $in_fh, '<', $filename or die "Cannot open $filename for reading: $!"; my $first_line = <$in_fh>; open my $out_fh, '>', "$filename.tmp" or die "Cannot open $filename.tmp for writing: $!"; $first_line =~ s/some translation/goes here/; print {$out_fh} $first_line; print {$out_fh} $_ while <$in_fh>; # sysread/syswrite is probably better close $in_fh; close $out_fh; # overwrite original with modified copy rename "$filename.tmp", $filename or warn "Failed to move $filename.tmp to $filename: $!";
Изменение, о котором вы упоминаете (замена каждого пробела подчеркиванием), не изменяет длину строки, поэтому теоретически это можно сделать на месте.
Внимание!- непроверено!
head -n 1 yourfile | sed -e 's/ /_/g' > tmpfile dd conv=nocreat,notrunc if=tmpfile of=yourfile
Я не так уверен в параметрах
Пожалуйста, обратите внимание, что если вы хотите сделать любое другое преобразование, которое может изменить длину линии, не делайте этого, Не делайте этого. тебе придется сделать полную копию. что-то вроде этого:conv=...
, но кажется, что он должен заставитьdd
перезаписать начало исходного файла преобразованной строкой.head -n 1 yourfile | sed -e 's/ /_/g' > tmpfile tail -n + 2 | cat tmpfile - > transformedfile
Это может быть решением :
use Tie::File; tie my @array,"Tie::File","path_to_file"; $array[0] = "new text"; untie @array;
Tie:: File - один из модулей , которые я использую больше всего, и он очень прост в использовании . Каждый элемент массива представляет собой строку в файле . Одним из недостатков , однако, было бы то, что это загружает весь файл в память .