Intereting Posts
перенаправление на проблемы с файлом nohup и pipe Является ли Mac OS X UNIX? Нужна помощь в настройке Xorg.conf для монитора 6 Big Desktop Rfkill отказывается разблокировать WiFi-устройство Возможные последствия slurmstepd: error: Превышение предела памяти в какой-то момент? Multipath для логического тома в промежуточной виртуальной машине Как установить время и дату из Интернета? Как запустить процесс на ночь на удаленном сервере после выхода из системы ssh Ошибка разрешения сценария резервного копирования Как рассчитать, скажем, продолжительность выхода? Прочитайте переменную с «read» и сохраните обратную косую черту, введенную пользователем rsync over ssh без ввода пароля каждый раз Как изменить ввод сценария в качестве первого аргумента в CLI? Экран / Minicom многострочная проблема Должна ли опция монтирования nodatacow использоваться в btrfs на сервере базы данных? Отключает ли он контрольные суммы бит-бит?

Искать значение только в одном столбце wo с помощью awk, sed или perl

У меня есть файл, который выглядит так:

Marketing Ranjit Singh FULLEagles Dean Johnson Marketing Ken Whillans FULLEagles Karen Thompson Sales Peter RobertsonPARTGolden TigersRich Gardener President Sandeep Jain CONTWimps Ken Whillans Operations John Thompson PARTHawks Cher Operations Cher CONTVegans Karen Patel Sales John Jacobs FULLHawks Davinder Singh Finance Dean Johnson FULLVegans Sandeep Jain EngineeringKaren Thompson PARTVegans John Thompson IT Rich Gardener FULLGolden TigersPeter Robertson IT Karen Patel FULLWimps Ranjit Singh 

Я хочу использовать команду grep для поиска «John» во втором столбце wo, который ищет последний столбец, но для каждого «Джона» во втором столбце я хочу вывести последний столбец.

Конечный результат должен выглядеть следующим образом:

  John Thompson Cher John Jacobs Davinder Singh Dean Johnson Sandeep Jain 

 #! /bin/bash while read line; do if [[ ${line:11:15} =~ John ]]; then echo " ${line:11:15} ${line:43}" fi done <file 

Вы можете выполнить выбор в grep , сопоставляя правильное количество символов от начала строки:

 grep -E '^.{11,22}John' 

John должен начинать и заканчивать в пределах столбцов 11-26.

Замена некоторых столбцов пробелом не входит в возможности grep. С GNU grep вы можете использовать -o для вывода только соответствующей части, но вы не сможете комбинировать два столбца с дополнительным пробелом между ними.

 tab=$(printf '\t') cut -c12-26 file | paste - file | grep "^[^$tab]*John" | cut -c1-16,60- 

Как Жиль сказал, что вы не можете сделать это с помощью grep одиночку. grep означает g/re/p (команда ed/ex/vi ), то есть печатать строки, соответствующие re.

Давайте объединим некоторые намеки на только что продемонстрированные решения.

От Стефана + Жиля:

 grep -E '^.{11,22}John' source.txt | cut -c12-26,44- # or, if you want only "John " and not Johnson, add a space after John. grep -E '^.{11,22}John ' source.txt | cut -c12-26,44- 

Здесь вам нужно использовать /bin/grep а также /bin/cut .

От Жиля + Хауке:

 grep -E '^.{11,22}John' source.txt | while read line; do echo "${line:11:14} ${line:43}"; done 

Здесь вам нужно использовать /bin/grep а также echo . В современной оболочке вы находите echo как встроенную команду, поэтому она требует меньше.

Решение Hauke ​​является менее дорогостоящим с точки зрения установленных программ: для этого требуется только echo (встроенный so bash ), но даже не /bin/grep .


Обновление Давайте немного поиграем.
В повседневной жизни мы запускаем фрагмент кода, созданный «на лету» и использующийся, возможно, никогда; не всегда бывает удобно проводить наше человеческое время, чтобы оптимизировать его или попробовать разные варианты … но semel in anno licet insanire : с другой стороны, и с большой вероятностью это был case-study question , возможно, даже домашняя работа, а не совершенно ясно. В этой оптике и ИМХО полезны все различные подходы и решения.

Мы все согласны, похоже, что для большого количества строк лучше (быстрее) использовать скомпилированную программу, а затем последовательность команд оболочки. Но что это такое? Я думаю, что цифры (и сюжеты) могут исправить идеи лучше, чем только слова: так что давайте посмотрим.

Здесь рецепт : был подготовлен набор файлов с растущим числом строк, N. Каждая строка была случайно извлечена из 11 оригиналов, размещенных здесь.
Используемые значения N
11 22 55 110 220 550 1100 2200 5500 11000 110000 1100000 11000000 .

Обследованный фрагмент :

  • Cut+Paste+Grep+Cut tab=$(printf '\t') ; cut -c12-26 file | paste - file | grep "^[^$tab]*John" | cut -c1-16,60- tab=$(printf '\t') ; cut -c12-26 file | paste - file | grep "^[^$tab]*John" | cut -c1-16,60- tab=$(printf '\t') ; cut -c12-26 file | paste - file | grep "^[^$tab]*John" | cut -c1-16,60- – Зеленый
  • Only Grep – Blue grep -E '^.{11,22}John' source.txt . Просто grep без отформатированного вывода по запросу.
  • Grep+Cut – Red [ grep -E '^.{11,22}John' source.txt | cut -c12-26,44- grep -E '^.{11,22}John' source.txt | cut -c12-26,44- ].
  • Grep+While – Violet [см. Выше в этом ответе, grep before и while while].
  • Цикл While loop – Желтый полный раствор bash, который не требует grep

Для каждого размера файлов и фрагментов было выполнено несколько повторений NRep начиная с 400 (для более коротких файлов) и уменьшалось с N до 100, 10 и 1 для последнего.
Было записано значение Time per line , Tpl , ака реального времени, измеренное встроенным time функции и усредненное по NRep и N. Поскольку и Tpl, и N span по степеням 10, был нанесен общий логарифм (на основание 10 или степень 10). Описанные линии – это кривые Безье, которые касаются каждой точки.

Полный тренд * Время на линию * vs * Количество строк *

При больших значениях N время на линию становится почти постоянным. Это так называемое асимптотическое поведение. Как и ожидалось, чем меньше скомпилированная программа использовала число, тем быстрее результат.

Кроссовер

Напротив, с небольшими файлами результат противоположный. Эффективность разных кодов пересекает друг друга в области, которая (для нашего примера) составляет от 40 до 140 строк. Даже если это правда, что для небольших файлов мало даже общего человеческого времени , то такое же рассмотрение больше не действует, когда нужно работать с большим количеством маленьких файлов: чистый код bash (желтый), который асимптотически равен 8.12 в несколько раз медленнее, чем зеленый, и даже в 157 раз медленнее , чем красный (для 11-метрового файла он использует 334,56 с вместо 41,21 с зеленого и 2,16 красного) вместо 2,16 и 1,58 раз быстрее для 11 строк один, когда он использует 1.20s для 400 повторений вместо 1.89s красного или 2.59s зеленого.

Вывод: чем больше вы знаете, тем лучше вы бросаете вызов , и всегда проверяйте, когда сможете! 🙂


Ps> Аналогичное соображение может быть сделано в отношении времени пользователя и времени sys , но с немного другой областью пересечения.

bash 4.3.11 (1) -release
паста (GNU coreutils) 8.21
cut (GNU coreutils) 8.21
grep (GNU grep) 2.16
kernel 3.13.0-24-generic x86_64