2016-02-21 2 views
2

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

9.975 1.49000000  0.295 0  0.4880 0.4929 0.5113 0.5245 2.016726  1.0472 -30.7449  1 
9.975 1.49000000  0.295 1  0.4870 0.5056 0.5188 0.5045 2.015859  1.0442 -30.7653  1 
9.975 1.50000000  0.295 0  0.5145 0.4984 0.4873 0.5019 2.002143  1.0854 -30.3044  2 

есть способ, чтобы извлечь каждую строку, в которой значение в колонке два не равно значение в столбце два в следующей строке? I.e. из этих трех строк я хотел бы извлечь второй, так как 1.49 не равен 1.50. Может быть, с sed или awk?

Это, как я это сделать в MATLAB:

myline = 1; 
mynewline = 1; 
while myline < length(myfile) 
    if myfile(myline,2) ~= myfile(myline+1,2) 
     mynewfile(mynewline,:) = myfile(myline,:); 
     mynewline = mynewline+1; 
     myline = myline+1; 
    else 
     myline = myline+1; 
    end 
end 

Однако мои файлы настолько велики, теперь, когда я предпочел бы, чтобы осуществить эту добычу в терминале перед передачей их на моем ноутбуке.

ответ

3

Awk должен делать.

<data awk '($2 != prev) {print line} {line = $0; prev = $2}' 

Краткое введение в AWK: программы AWK состоит из набора condition {code} блоков. Он работает по строкам. Когда условие не задано, блок выполняется для каждой строки. BEGIN Условие выполняется перед первой строкой. Каждая строка разделяется на поля, доступные с помощью $_number_. Полная строка находится в $0.

Здесь я сравниваю второе поле с предыдущим значением, если оно не соответствует I print всей предыдущей строке. Во всех случаях я сохраняю текущую строку в line, а второе поле - prev.

И если вы действительно этого хотите, внимательно следите за поплавковыми сравнениями - что-то вроде abs($2 - prev) < eps (в awk нет abs), вам нужно определить его самостоятельно, а eps - достаточно малое число). Я на самом деле не уверен, что awk преобразуется в число для тестирования равенства, если вы не в безопасности со строковыми сравнениями.

+0

Первая строка не требуется - из приведенного выше примера, только второй. Не могли бы вы подробнее рассказать о функции вашей команды? Я пытаюсь проверить это прямо сейчас, но ничего не происходит. – Ango

+0

Вы не указали, где находятся ваши данные, поэтому я по умолчанию был stdin. Чтобы фактически использовать его, вам нужно поместить ваши данные в файл с каким-то именем, например 'data', а затем сделать' liborm

+0

Ах, получилось - но он печатает третью строку из приведенного выше примера. Насколько я понимаю эту строку, это то, что происходит: сначала мы берем -1 в качестве ссылки, а затем переходим через столбец номер 2 и сравниваем каждое значение с ссылкой.в случае, если значения не совпадают, то текущая строка печатается, и опорное значение устанавливается равным значению из колонки 2 в этой строке. теперь мне нужно только выяснить, как заставить его распечатать предыдущую строку! – Ango

1

Попробуйте следующую команду:

awk '$2 != field && field { print line } { field = $2; line = $0 }' infile 

Он сохраняет предыдущую строку и второе поле, сравнивая в следующем цикле с текущими значениями строки. Проверка && field полезна, чтобы избежать пустой строки в начале файла, когда $2 != field будет соответствовать, потому что переменная пуста.

Это дает:

9.975 1.49000000  0.295 1  0.4870 0.5056 0.5188 0.5045 2.015859  1.0442 -30.7653  1 
+0

Он почти работает! Только одно, я не могу понять: эта команда дает две из трех строк, которые нужно извлечь из заданного файла. Но эта команда проходит через все строки файла, не так ли? .. – Ango

2

Это может работать для вас (GNU СЭД):

sed -r 'N;/^((\S+)\s+){2}.*\n\S+\s+\2/!P;D' file 

прочитанной две строки в то время. Согласование шаблона в первых двух столбцах и печать только первой строки, когда второй столбец не совпадает.

+0

Не могли бы вы рассказать мне, как изменить эту команду для печати (в случае, если второй столбец не совпадает) не только с первой строкой, но и с последней n строк? – Ango

+1

@Ango Я не понимаю ваш комментарий. Примеры говорят лучше, чем слова. – potong

+0

Недостаточно места в комментариях к примерам :) Я хотел бы знать, как изменить эту команду так, чтобы она выполняла следующие действия: Прочитайте по две строки за раз. Согласование шаблона в первых двух столбцах и печать только первой строки ** и предыдущей строки **, когда второй столбец не совпадает. Думаю, нужно было бы читать три строки за раз, например, сделать это. – Ango

Смежные вопросы