2015-05-25 3 views
0

Я хочу перебрать несколько файлов и их соответствующие строки в файле. Я уже успешно это сделал. Хотелось бы, чтобы я теперь хотел удалить строки в файле на основе числового значения в одном из столбцов.Удалить строку из файла на основе значения столбца в Perl

Если у меня вход, такие как это:

XP.sta1 -41.5166 0.0513 0.6842 0.1794 0 CPHI.BHZ 300.2458 -42.2436 
XP.sta2  3.5972 0.0500 0.7699 0.1213 0 E000.BHZ 300.5616  2.5545 
XP.sta3  3.7112 0.0267 0.7813 0.1457 0 E002.BHZ 300.6140  2.6160 
XP.sta4  4.2891 0.0214 0.6870 0.1308 0 E004.BHZ 301.2073  2.6006 

где девятый столбец является хочу посмотреть. Мне нужно удалить это значение в столбце 9 (давайте присвойте ему переменную $ time), в том случае, если это время $> 10 или меньше -10, удалите всю строку. До сих пор я попытался это:

unless (($time < -10) || ($time > 10) {  
print OUT2 ($stlat," ",$stlon," ",$eqlat," ",$eqlong," ",$eqdepth," ",$time,"\n"); 
}} 

Однако я получаю следующий результат:

XP.sta1 -41.5166 0.0513 0.6842 0.1794 0 CPHI.BHZ 300.2458 2.5545 
XP.sta2  3.5972 0.0500 0.7699 0.1213 0 E000.BHZ 300.5616 2.6160 
XP.sta3  3.7112 0.0267 0.7813 0.1457 0 E002.BHZ 300.6140  2.6006 
XP.sta4  4.2891 0.0214 0.6870 0.1308 0 E004.BHZ 301.2073 

Как вы можете видеть, что вся линия не удаляется - просто значение, которое соответствует истинным " если "условие", а затем другие значения перемещаются в 9-м столбце. Как удалить всю строку, а не только номер девятого столбца?

Вот где я хотел бы изменить свой сценарий:

open(TABLEC,$File); 
    @tablec = <TABLEC>; 
    for ($j = 2; $j < $stop; $j++) { 
     chomp ($tablec[$j]); 
     ($netSta,$delayTime) = (split /\s+/,$tablec[$j])[1,9] ; 
     } 

В этом цикл, я пробегаем по каждому файлу, чтение в линии от 2-х до «остановки», и chopming возвратного характера. Я установил 9-й столбец в переменную времени задержки. Поэтому я перебираю каждую строку, но я не хочу ничего печатать (это происходит позже в моем скрипте). Я просто хотел бы удалить эту целую строку, так что позже в моем скрипте, когда мне придется печатать строки, строка, где значения девятого столбца> abs (10) не существует.

+0

Мы должны увидеть остальную часть вашего кода – Borodin

+1

Если диапазон имеет 0 в качестве средней точки, то вы можете использовать 'abs' (как @Borodin указывает), так что может быть коротким, как 'perl -anE 'сказать, если abs $ F [8] <= 10;' datafile.txt'. –

ответ

1

Я просто пропустить строку:

use warnings; 
use strict; 

while(<DATA>){ 
    my @split = split; 
    next if $split[8] > 10 or $split[8] < -10; 
    print "$_\n"; 
} 

XP.sta2  3.5972 0.0500 0.7699 0.1213 0 E000.BHZ 300.5616  2.5545 
XP.sta3  3.7112 0.0267 0.7813 0.1457 0 E002.BHZ 300.6140  2.6160 
XP.sta4  4.2891 0.0214 0.6870 0.1308 0 E004.BHZ 301.2073  2.6006 
+0

Привет Фугу, я, возможно, был слишком широк в своем описании того, что мне нужно делать. Я хотел бы удалить всю строку, начинающуюся с XP.sta1 (столбец 0) через столбец 8. Затем все строки, следующие за строкой, где условие столбца 8 истинно, просто переместите их вверх. –

+0

@ user78872 - см. Обновление – fugu

+0

О, правда! Я забыл о следующем, если оператор. Я собираюсь реализовать этот оператор в своем скрипте, чтобы узнать, могу ли я получить желаемый результат. Спасибо за вашу помощь фугу. –

0

Вы не показаны достаточно кода, чтобы диагностировать проблему, но то, что вы спрашиваете очень просто сделать, как этот

use strict; 
use warnings; 

while (<DATA>) { 
    print unless abs((split)[8]) > 10; 
} 

__DATA__ 
XP.sta1 -41.5166 0.0513 0.6842 0.1794 0 CPHI.BHZ 300.2458 -42.2436 
XP.sta2  3.5972 0.0500 0.7699 0.1213 0 E000.BHZ 300.5616  2.5545 
XP.sta3  3.7112 0.0267 0.7813 0.1457 0 E002.BHZ 300.6140  2.6160 
XP.sta4  4.2891 0.0214 0.6870 0.1308 0 E004.BHZ 301.2073  2.6006 

выход

XP.sta2  3.5972 0.0500 0.7699 0.1213 0 E000.BHZ 300.5616  2.5545 
XP.sta3  3.7112 0.0267 0.7813 0.1457 0 E002.BHZ 300.6140  2.6160 
XP.sta4  4.2891 0.0214 0.6870 0.1308 0 E004.BHZ 301.2073  2.6006 
+0

Смотрите мои правки вверху в моем оригинальном посте. –

+0

@ user78872: Я видел это, но я не совсем понимаю, – Borodin

0

Я думал, ваш вопрос был дан ответ, буит вот что-то, что должно помочь вам с содержанием вашего редактирования

Некоторые моменты, на ваш код

  • Идентификаторы для лексических переменных должен содержать только ниже буквенные обозначения, десятичные цифры и символ подчеркивания. Заглавные буквы зарезервированы для глобальных переменных, таких как константы и имена пакетов

  • Вы должны использовать лексического файл обрабатывает с три параметра формы open

  • Вы всегда должны убедиться, что open удалось.В случае сбоя программа должна die и включать в себя значение $! в строке матрицы, чтобы показать почему операция провалилась

    Вместе эти точки означают, что

    open(TABLEC, $File); 
    

    становится

    open my $tablec_fh, '<', $File or die qq{Unable to open "$File" for input: $!}; 
    
  • Вы можете chomp весь массив сразу с chomp @tablec

  • Вам следует избегать циферблата C for, так как это редко бывает хорошим выбором. Perl позволяет выполнять итерацию по диапазону, и вы должны это использовать. Так

    for ($j = 2; $j < $stop; $j++) { ... } 
    

    становится

    for my $j (2 .. $stop-1) { ... } 
    
  • split /\s+/ почти всегда быть split ' '. Последний является особым случаем для оператора, который не позволяет ему возвращать начальное пустое поле, если строка параметров имеет ведущие пробелы. Если вы звоните split без каких-либо параметров, то по умолчанию для split ' ', $_

Вот переписан ваш образец кода, который принимает эти точки во внимание. Я надеюсь, что это лучше подходит, чем мой предыдущий ответ

open my $tablec_fh, '<', $File or die qq{Unable to open "$File" for input: $!}; 
my @tablec = <$tablec_fh>; 
chomp @tablec; 
close $tablec_fh; 

for my $i (2 .. $stop-1) { 
    my $row = $tablec[$i]; 
    my ($net_sta, $delay_time) = (split ' ', $row)[0,8]; 
    next unless abs($delay_time) <= 10; 

    # Do stuff with $row 
}