Як підкреслити рядки, які мають певне значення у певному стовпці?


9

У мене є такий файл

  200.000    1.353    0.086
  200.250    1.417    0.000
  200.500    1.359    0.091
  200.750    1.423    0.000
  201.000    1.365    0.093
  201.250    1.427    0.000
  201.500    1.373    0.093
  201.750    1.432    0.000
  202.000    1.383    0.091
  202.250    1.435    0.000
  202.500    1.392    0.087
  202.750    1.436    0.000
  203.000    1.402    0.081
  203.250    1.437    0.001
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045  

Я хотів би проглядати лише ті рядки, у яких у першому стовпці є десяткові .000 і .500 лише так, щоб результат був таким

  200.000    1.353    0.086
  200.500    1.359    0.091
  201.000    1.365    0.093
  201.500    1.373    0.093
  202.000    1.383    0.091
  202.500    1.392    0.087
  203.000    1.402    0.081
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045  

2
Це виглядає досить просто. Що ви пробували поки що? З якими проблемами виник ваш код?
John1024

можливо, це вам легко, але я спробував з grep '.000' | grep '.005', але він також сортує рядки, які мають однакове значення в інших стовпцях
Mohsen El-Tahawy

3
Дуже добре. Люди тут набагато симпатичніші, якщо ви виявляєте чесну спробу вирішити проблему самостійно. Код у вашому коментарі це показує. Надалі, якщо ви включите подібні спроби у своє запитання, швидше за все, ви отримаєте кращі відповіді.
John1024

Відповіді:


14

Ви не використовуєте grep. Використовуйте awk.

"your data" | awk '$1 ~ /\.[05]00/'

Дуже добре. Як написано, код залежить від того, що після десятки буде рівно три цифри. Це було б більш надійним у використанні awk '$1 ~ /\.[05]0*$/'.
John1024

1
@ John1024, насправді як написаний код залежить від того, що після десяткової цифри буде принаймні три цифри. Я би схилявся до awk '$1 ~ /\.[05]00$/'себе (вимагаю рівно трьох цифр), якщо б у мене не було підстави думати, що вхідні дані очікуються змінних десяткових знаків.
Wildcard

2
@Wildcard Якщо їх більше трьох, код може вийти з ладу. Наприклад: echo 0.5001 | awk '$1 ~ /\.[05]00/'. Надійно працює лише в тому випадку, якщо їх рівно три.
John1024

4
awk '$1 ~ /\.[50]00/ { print $0 }' myFile.txt

Перший стовпець $1буде узгоджений з /\.500|\.000/точками, які будуть виведені, щоб вони були буквальними точками, не переробити жодного символу, ~це часткове збіг, і надрукувати весь рядок$0


2
Немає підстав включати { print $0 }; це дія за замовчуванням Awk.
Wildcard

4

Я хотів би проглядати лише ті рядки, які мають у першому стовпці десятки .000 та .500

Моя перша думка

grep '^ *[0-9][0-9][0-9]\.[50]00' filename

Швидкий тест за допомогою WSL

$ head testdata
              200.000    1.353    0.086
              200.250    1.417    0.000
              200.500    1.359    0.091
              200.750    1.423    0.000
              201.000    1.365    0.093
              201.250    1.427    0.000
              201.500    1.373    0.093
              201.750    1.432    0.000
              202.000    1.383    0.091
              202.250    1.435    0.000
$ grep '^ *[0-9][0-9][0-9]\.[50]00' testdata
              200.000    1.353    0.086
              200.500    1.359    0.091
              201.000    1.365    0.093
              201.500    1.373    0.093
              202.000    1.383    0.091
              202.500    1.392    0.087
              203.000    1.402    0.081
              203.500    1.412    0.073
              204.000    1.423    0.065
              204.500    1.432    0.055
              205.000    1.441    0.045

Є більш стислі способи цього висловити.

$ grep -E '^ *[0-9]{3}\.[50]00' testdata
              200.000    1.353    0.086
              200.500    1.359    0.091
              201.000    1.365    0.093
              201.500    1.373    0.093
              202.000    1.383    0.091
              202.500    1.392    0.087
              203.000    1.402    0.081
              203.500    1.412    0.073
              204.000    1.423    0.065
              204.500    1.432    0.055
              205.000    1.441    0.045

Якщо перший стовпець може містити іншу, ніж 3-розрядну цілу частину

grep -E '^ *[0-9]+\.[05]00' testdata

За певних обставин вам може знадобитися використовувати [:digit:]замість [0-9].

І так далі.

man grep твій друг.


Це використання grepпростіше у використанні, ніж моє. Я б не опублікував відповіді, якби я бачив це першим. Хороша робота!
Йокай

2

Залежно від випадку використання, ви також можете використовувати фактичні числові операції:

$ awk '{a = $1 % 1} a == 0 || a == 0.5' /tmp/foo
  200.000    1.353    0.086
  200.500    1.359    0.091
  201.000    1.365    0.093
  201.500    1.373    0.093
  202.000    1.383    0.091
  202.500    1.392    0.087
  203.000    1.402    0.081
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045

Тестовано на BSD awk (OSX El Capitan, 20070501) та GNU awk 4.1.4.


1
Попередження: тестування точної рівності з плаваючою комою (що використовує awk) часто дає «неправильні» результати, якщо значення не мають дробової частини (і не надто великі за величиною) або дробова частина є «двійковою» (рівно половина, а квартал тощо), що стосується даних цього Q, але не для багатьох інших, схожих на непосвячені.
dave_thompson_085

1
@ dave_thompson_085 справді, але з gawk ви можете використовувати довільну арифметику точності , правда, я тут їх не використовую.
муру


2

З awk:

$>awk '$1%.5==0' data.tsv 
200.000 1.353   0.086
200.500 1.359   0.091
201.000 1.365   0.093
201.500 1.373   0.093
202.000 1.383   0.091
202.500 1.392   0.087
203.000 1.402   0.081
203.500 1.412   0.073
204.000 1.423   0.065
204.500 1.432   0.055
205.000 1.441   0.045

З mlr:

$>mlr --ifs tab --onidx filter '$1%.5==0' data.tsv 
200.000 1.353 0.086
200.500 1.359 0.091
201.000 1.365 0.093
201.500 1.373 0.093
202.000 1.383 0.091
202.500 1.392 0.087
203.000 1.402 0.081
203.500 1.412 0.073
204.000 1.423 0.065
204.500 1.432 0.055
205.000 1.441 0.045

2

Гаразд, трохи пізно додаю в свій внесок, але я думаю, що воно того варте.

Вимога, яку необхідно виконати, за ОП - це перший стовпець, що має десяткове значення .000або .500тільки. Немає жодних умов щодо провідного значення, ні за діапазоном, ні за довжиною. Для надійності не слід вважати, що обмежує будь-що, крім того, що перед першим стовпцем (або це вже не перший стовпець) немає порожніх символів і що вміст першого стовпця матиме десяткові крапки ., в ньому десь.

Оперативна програма хоче використовувати grep, яка буде надрукувати весь рядок, коли буде знайдено відповідність, тому єдине, що потрібно зробити, - це створити шаблон, який відповідає всім і лише тому, що потрібно.

Сама простота і відсутність причин використовувати sedабо awkяк "grep" можуть обробляти джерело у вигляді файлу або труби.

Для grepвикористання файлівgrep '^[^.]*\.[05]0\{2\}\s' the_file.txt

До grepтруби, використовуйтеmy_command | grep '^[^.]*\.[05]0\{2\}\s'

Візерунок такий: ^починати на початку рядка; [^.], збігаються з будь-яким недесятковим символом; *, якомога більше разів (включаючи жоден); \., відповідність десяткової крапки; [05], відповідати або п'ятірці, або нулю; 0\{2\}, співставити ще 2 нулі (зворотна коса риса перед відкритим і закритим дужкою запобігає спробі оболонки зробити розширення дужок); \s, відповідати символу пробілу (означає кінець стовпця - для використання в іншому випадку використання замініть роздільником стовпців, як правило, коміном, комою або вкладкою \t).

Зауважте, що це відповідатиме точно тому, що запитувала ОП. Він не збігається .5000або .0000хоча б чисельно еквівалентний, оскільки візерунок шукає п’ять або нуль, а за ним ще точно два нулі, а потім пробіл. Якщо це важливо, то всі інші відповіді, поки що, не відповідають тому, що вони будуть відповідати будь-якій кількості нулів, більше 1, після тестової цифри. І крім відповіді по FloHimself, вони будуть відповідати нічого в другому стовпці , який починається .000 або .500, в тому числі .0003і .500T, і один на FloHimself буде відповідати все , що математично еквівалентно .0і.5, скільки б не було нулів. Останній, хоч і не відповідає тому, що заявлено в ОП, все одно відповідає тому, що ОП потребує.

Нарешті, якщо awkбажана потужність і швидкість, навіть незважаючи на те, що просив ОП grep, команда буде:

З файлом awk '$1 ~ /[^.]\.[05]0{2}$/' the_file.txt

З трубою my_command | awk '$1 ~ /[^.]\.[05]0{2}$/'


1

Якщо ви наполягаєте на використанні grep, то це може допомогти вам. Перший вихід, який ви надаєте, я зберег у текстовому файлі під назвою "file.txt", а потім застосував таку команду:

grep -e '2[^ ]*.000' file.txt & grep -e '2[^ ]*.500' file.txt

Що дає вихід:

200.000    1.353    0.086
200.500    1.359    0.091
201.500    1.373    0.093
201.000    1.365    0.093
202.500    1.392    0.087
202.000    1.383    0.091
203.500    1.412    0.073
203.000    1.402    0.081
204.500    1.432    0.055
204.000    1.423    0.065
205.000    1.441    0.045

Вам не доведеться зберігати висновок у текстовий файл, якщо він вже є у файлі. Але у випадку, якщо він не зберігається у файл, ви також можете передавати дані в команду grep, яку я надав, і вона повинна працювати принаймні до самого першого номера 2, у першому стовпці вже немає а 2. У цей момент вам потрібно буде оновити команду grep відповідним символом для правильного друку.

Те, що відбувається з цією подвійною grepкомандою, - це те, що перша grepнадсилається на задній план разом з &оператором. Після відправки у фоновий режим наступна grepкоманда виконується відразу після цього, даючи вам рівномірний вихід. Для того, щоб завдання, яке вам потрібно виконати, було легше виконати, ви повинні слідувати прикладу, який дали інші та використали awkабо навіть sed.

(редагувати)

Це в жодному разі не найкраще чи найефективніше використання грепу для ваших потреб, але воно повинно бути достатньо, щоб ви могли трохи пограти і краще відчути греп.


Перший процес працює у фоновому режимі, але не демонізований, що включає біг у фоновому режимі, але зовсім трохи більше. І дуже малоймовірно, що виробництво буде в тому ж порядку, що і вхідне; навіть у вашому зовсім маленькому прикладі це вже пішло не так на третьому рядку.
dave_thompson_085

Він не згадує, що вихід повинен бути у визначеному порядку. Тільки те, що він повинен бути специфічним для першого .500та .000першого стовпця. Якщо це потрібно в певному порядку, наприклад, в найменшому для найбільшого, це легко зробити. Однак перші 3 цифри перших друкованих стовпців принаймні в найбільшому порядку. Це результат 2[^ ]*.000та 2[^ ]*.500. Це цілком відповідає тому, що просив ОП.
Йокай

Також відзначте мою редакцію щодо відмови від ефективності для команди, яку я надав.
Йокай
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.