2017-02-22 10 views
0

У меня есть текстовый файл, имеющий дату и время в указанной ниже форме на 4-й строке файла:Удалить дату и время из текстового файла

[0x1FFD]  LOG     2017/02/22 06:20:48.644 Diagnostic Version        Length: 0149            255 

Теперь я должен удалить строку "2017/02/22 06: 20: 48.644 "в файле.

Эта дата и время не являются постоянными и будут меняться при каждом сохранении файла (он принимает текущую дату и время).

Поскольку я не являюсь perl-кодером, мне сложно разобраться в этом.

ПРИМЕЧАНИЕ: Мне нужно внести изменения только в входной файл. Мне не нужно создавать отдельный выходной файл.

Заранее благодарен!

+0

Возможно, вы можете прочитать файл, а затем использовать для него регулярное выражение для поиска и замены метки времени. – Mohit

+0

Не могли бы вы предложить регулярное выражение для получения времени и даты – gollusingh09

+1

Если формат _always_ одинаковый, вот простая версия: '$ line = ~ s | \ d {4}/\ d {2}/\ d { 2} \ d {2}: \ d {2}: \ d {2} \. \ D {3} ||; '. Вы просматриваете строки ('while (<$fh>)'), имеют вышеперечисленное выражение и затем записываете строку в новый файл. Если совпадения нет (нет даты в строке), в регулярном выражении ничего не происходит, и эта строка записывается без изменений, т.е. скопировано. После обработки файла вы перезаписываете оригинал (используйте 'move' из' File :: Copy'). Вы не можете «редактировать» оригинал, вам нужно записать новый файл, а затем скопировать его по оригиналу. – zdim

ответ

2
use strict; 
use warnings; 
my $str = " [0x1FFD]  LOG   2017/02/22 06:20:48.644 Diagnostic Version  and more stuff"; 
$str =~ s|\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}\.\d{3}||; 
print $str; 

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

Как это

use strict; 
use warnings; 
open FILE, "<", "filename.log" or die $!; 
my @list = <FILE>; 
foreach my $str(@list) { 
    $str =~ s|\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}\.\d{3}||; 
    print $str; 
} 
close(FILE); 

Так оттуда вы можете понять, как записать его обратно в исходный файл. :)

+1

Второй 's ///' заменяет любые два пробела одним на всех строках, которые имеют два пробела - даже те, которые не были сопоставлены с первым ////. Комментарии.Использование 'open my $ fh, ...' лучше, чем 'FILE' или такое. Любые пробелы в регулярном выражении трудно читать, а два рядом друг с другом вдвойне. Возможно, сбегите от них или используйте '\ x20', или' \ N {SPACE} ', или' [] '(класс символов :) – zdim

+0

@zdim, да, единственная причина, по которой я делаю///g', чтобы показать результаты, исключив некоторые пробелы из строки. Спасибо за другие предложения, изменит код и тест :) –

+0

Еще один комментарий. Поскольку файл читается в контексте списка, 'close (FILE)' принадлежит сразу после этого, _before_ цикл. Это может иметь значение, поскольку таким образом OP перенаправляет вывод на перезапись того же файла. Поэтому лучше закройте его, прежде чем мы начнем печатать. (Отпечатки на терминале могут быть буферизированы по строке, поэтому они идут вправо, как они есть. Переадресация оболочки _is_ буферизована, но она может сразу открываться и усекать.) // Другим способом было бы открыть выходной файл, прочитать строки -line и распечатать его, а после цикла «переместить» его на оригинал (после закрытия дескрипторов файла). – zdim

1

Вы можете использовать модуль Tie::File для обновления входного файла при одном вызове.

use warnings; 
use strict; 
use Tie::File; 

my $str = 'data1.txt'; 

tie my @lines, 'Tie::File', $str or die $!; 

my $joinLines = join "\n", @lines; 

Либо использовать # 1 или # 2 для на основе модификации регулярных выражений

#1. $joinLines=~s/(LOG\s)(.*?)(\sDiagnostic Version)/$1$3/g; 
#2. $joinLines =~ s/\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}\.\d{3}//; 


print $joinLines; 

@lines = split /\n/, $joinLines; 

untie @lines; 

Пожалуйста, проверьте и испытания на вашем конце.